

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=dark>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/deng-2022/blog_2/img/fluid.png">
  <link rel="icon" href="/deng-2022/blog_2/img/icon/dw.png">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="author" content="Memory">
  <meta name="keywords" content="">
  
    <meta name="description" content="🎨 构建强大的搜索引擎,Elasticsearch入门到精通的完整学习指南">
<meta property="og:type" content="article">
<meta property="og:title" content="揭秘 Elasticsearch 的神奇能力：从数据搜索到实时分析的终极指南">
<meta property="og:url" content="https://atomgit.com/deng-2022/blog_2/2023/09/19/%E6%8F%AD%E7%A7%98%20Elasticsearch%20%E7%9A%84%E7%A5%9E%E5%A5%87%E8%83%BD%E5%8A%9B%EF%BC%9A%E4%BB%8E%E6%95%B0%E6%8D%AE%E6%90%9C%E7%B4%A2%E5%88%B0%E5%AE%9E%E6%97%B6%E5%88%86%E6%9E%90%E7%9A%84%E7%BB%88%E6%9E%81%E6%8C%87%E5%8D%97/index.html">
<meta property="og:site_name" content="Memory&#39;s blog">
<meta property="og:description" content="🎨 构建强大的搜索引擎,Elasticsearch入门到精通的完整学习指南">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://atomgit.com/deng-2022/blog_2/img/artical/sea.jpg">
<meta property="article:published_time" content="2023-09-19T13:42:50.000Z">
<meta property="article:modified_time" content="2023-11-18T13:50:45.000Z">
<meta property="article:author" content="Memory">
<meta property="article:tag" content="经验">
<meta property="article:tag" content="Elasticsearch">
<meta property="article:tag" content="Kibana">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="https://atomgit.com/deng-2022/blog_2/img/artical/sea.jpg">
  
  
  
  <title>揭秘 Elasticsearch 的神奇能力：从数据搜索到实时分析的终极指南 - Memory&#39;s blog</title>

  <link  rel="stylesheet" href="https://lib.baomitu.com/twitter-bootstrap/4.6.1/css/bootstrap.min.css" />



  <link  rel="stylesheet" href="https://lib.baomitu.com/github-markdown-css/4.0.0/github-markdown.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/hint.css/2.7.0/hint.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.css" />



<!-- 主题依赖的图标库，不要自行修改 -->
<!-- Do not modify the link that theme dependent icons -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_hj8rtnfg7um.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_lbnruvf0jn.css">


<link  rel="stylesheet" href="/deng-2022/blog_2/css/main.css" />


  <link id="highlight-css" rel="stylesheet" href="/deng-2022/blog_2/css/highlight.css" />
  
    <link id="highlight-css-dark" rel="stylesheet" href="/deng-2022/blog_2/css/highlight-dark.css" />
  




  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    Fluid.ctx = Object.assign({}, Fluid.ctx)
    var CONFIG = {"hostname":"atomgit.com","root":"/deng-2022/blog_2/","version":"1.9.4","typing":{"enable":true,"typeSpeed":100,"cursorChar":"_","loop":false,"scope":[]},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"left","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"code_language":{"enable":true,"default":"TEXT"},"copy_btn":true,"image_caption":{"enable":true},"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"placement":"right","headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":false,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":true,"follow_dnt":true,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null,"path":"window.location.pathname","ignore_local":false}},"search_path":"/deng-2022/blog_2/local-search.xml"};

    if (CONFIG.web_analytics.follow_dnt) {
      var dntVal = navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack;
      Fluid.ctx.dnt = dntVal && (dntVal.startsWith('1') || dntVal.startsWith('yes') || dntVal.startsWith('on'));
    }
  </script>
  <script  src="/deng-2022/blog_2/js/utils.js" ></script>
  <script  src="/deng-2022/blog_2/js/color-schema.js" ></script>
  

  

  

  

  

  

  

  



  
<meta name="generator" content="Hexo 5.4.2"></head>


<body>
  

  <header>
    

<div class="header-inner" style="height: 75vh;">
  <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand" href="/deng-2022/blog_2/">
      <strong>Memory&#39;s blog</strong>
    </a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/deng-2022/blog_2/">
                <i class="iconfont icon-home-fill"></i>
                <span>首页</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/deng-2022/blog_2/archives/">
                <i class="iconfont icon-archive-fill"></i>
                <span>归档</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/deng-2022/blog_2/categories/">
                <i class="iconfont icon-category-fill"></i>
                <span>分类</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/deng-2022/blog_2/tags/">
                <i class="iconfont icon-tags-fill"></i>
                <span>标签</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/deng-2022/blog_2/about/">
                <i class="iconfont icon-user-fill"></i>
                <span>关于</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/deng-2022/blog_2/links/">
                <i class="iconfont icon-link-fill"></i>
                <span>友链</span>
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
              <i class="iconfont icon-search"></i>
            </a>
          </li>
          
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">
              <i class="iconfont icon-dark" id="color-toggle-icon"></i>
            </a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

  

<div id="banner" class="banner" parallax=true
     style="background: url('/deng-2022/blog_2/img/newBG/girl.jpg') no-repeat center center; background-size: cover;">
  <div class="full-bg-img">
    <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
      <div class="banner-text text-center fade-in-up">
        <div class="h2">
          
            <span id="subtitle" data-typed-text="揭秘 Elasticsearch 的神奇能力：从数据搜索到实时分析的终极指南"></span>
          
        </div>

        
          
  <div class="mt-3">
    
      <span class="post-meta mr-2">
        <i class="iconfont icon-author" aria-hidden="true"></i>
        Memory
      </span>
    
    
      <span class="post-meta">
        <i class="iconfont icon-date-fill" aria-hidden="true"></i>
        <time datetime="2023-09-19 21:42" pubdate>
          2023年9月19日 晚上
        </time>
      </span>
    
  </div>

  <div class="mt-1">
    
      <span class="post-meta mr-2">
        <i class="iconfont icon-chart"></i>
        
          49k 字
        
      </span>
    

    
      <span class="post-meta mr-2">
        <i class="iconfont icon-clock-fill"></i>
        
        
        
          123 分钟
        
      </span>
    

    
    
      
        <span id="leancloud-page-views-container" class="post-meta" style="display: none">
          <i class="iconfont icon-eye" aria-hidden="true"></i>
          <span id="leancloud-page-views"></span> 次
        </span>
        
      
    
  </div>


        
      </div>

      
    </div>
  </div>
</div>

</div>

  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="side-col d-none d-lg-block col-lg-2">
      
  <aside class="sidebar category-bar" style="margin-right: -1rem">
    





<div class="category-list">
  
  
    
    
    
    <div class="category row nomargin-x">
      <a class="category-item 
          list-group-item category-item-action col-10 col-md-11 col-xm-11" title="Elasticsearch"
        id="heading-45e23a169652aaf95ce80da844f3df0d" role="tab" data-toggle="collapse" href="#collapse-45e23a169652aaf95ce80da844f3df0d"
        aria-expanded="true"
      >
        Elasticsearch
        <span class="list-group-count">(2)</span>
        <i class="iconfont icon-arrowright"></i>
      </a>
      
      <div class="category-collapse collapse show" id="collapse-45e23a169652aaf95ce80da844f3df0d"
           role="tabpanel" aria-labelledby="heading-45e23a169652aaf95ce80da844f3df0d">
        
        
          
          
  <div class="category-post-list">
    
    
  </div>

          
  
    
    
    
    <div class="category-sub row nomargin-x">
      <a class="category-subitem 
          list-group-item category-item-action col-10 col-md-11 col-xm-11" title="Kibana"
        id="heading-5228fdd6f613af63fc73ee7c02ef8fb5" role="tab" data-toggle="collapse" href="#collapse-5228fdd6f613af63fc73ee7c02ef8fb5"
        aria-expanded="true"
      >
        Kibana
        <span class="list-group-count">(1)</span>
        <i class="iconfont icon-arrowright"></i>
      </a>
      
      <div class="category-collapse collapse show" id="collapse-5228fdd6f613af63fc73ee7c02ef8fb5"
           role="tabpanel" aria-labelledby="heading-5228fdd6f613af63fc73ee7c02ef8fb5">
        
        
          
          
  <div class="category-post-list">
    
    
  </div>

          
  
    
    
    
    <div class="category-sub row nomargin-x">
      <a class="category-subitem 
          list-group-item category-item-action col-10 col-md-11 col-xm-11" title="经验"
        id="heading-32a8e000e928e6dc255876d9fc0178b3" role="tab" data-toggle="collapse" href="#collapse-32a8e000e928e6dc255876d9fc0178b3"
        aria-expanded="true"
      >
        经验
        <span class="list-group-count">(1)</span>
        <i class="iconfont icon-arrowright"></i>
      </a>
      
      <div class="category-collapse collapse show" id="collapse-32a8e000e928e6dc255876d9fc0178b3"
           role="tabpanel" aria-labelledby="heading-32a8e000e928e6dc255876d9fc0178b3">
        
        
          
  <div class="category-post-list">
    
    
      
      
        <a href="/deng-2022/blog_2/2023/09/19/%E6%8F%AD%E7%A7%98%20Elasticsearch%20%E7%9A%84%E7%A5%9E%E5%A5%87%E8%83%BD%E5%8A%9B%EF%BC%9A%E4%BB%8E%E6%95%B0%E6%8D%AE%E6%90%9C%E7%B4%A2%E5%88%B0%E5%AE%9E%E6%97%B6%E5%88%86%E6%9E%90%E7%9A%84%E7%BB%88%E6%9E%81%E6%8C%87%E5%8D%97/" title="揭秘 Elasticsearch 的神奇能力：从数据搜索到实时分析的终极指南"
           class="list-group-item list-group-item-action
           active">
          <span class="category-post">揭秘 Elasticsearch 的神奇能力：从数据搜索到实时分析的终极指南</span>
        </a>
      
    
  </div>

        
      </div>
    </div>
  
        
      </div>
    </div>
  
    
    
    
    <div class="category-sub row nomargin-x">
      <a class="category-subitem collapsed
          list-group-item category-item-action col-10 col-md-11 col-xm-11" title="Redis"
        id="heading-e111446745a1825b862f8727ae63bce4" role="tab" data-toggle="collapse" href="#collapse-e111446745a1825b862f8727ae63bce4"
        aria-expanded="false"
      >
        Redis
        <span class="list-group-count">(1)</span>
        <i class="iconfont icon-arrowright"></i>
      </a>
      
      <div class="category-collapse collapse " id="collapse-e111446745a1825b862f8727ae63bce4"
           role="tabpanel" aria-labelledby="heading-e111446745a1825b862f8727ae63bce4">
        
        
          
          
  <div class="category-post-list">
    
    
  </div>

          
  
    
    
    
    <div class="category-sub row nomargin-x">
      <a class="category-subitem collapsed
          list-group-item category-item-action col-10 col-md-11 col-xm-11" title="项目"
        id="heading-31ecc0e65b4cd3e6b12577382bb56d6a" role="tab" data-toggle="collapse" href="#collapse-31ecc0e65b4cd3e6b12577382bb56d6a"
        aria-expanded="false"
      >
        项目
        <span class="list-group-count">(1)</span>
        <i class="iconfont icon-arrowright"></i>
      </a>
      
      <div class="category-collapse collapse " id="collapse-31ecc0e65b4cd3e6b12577382bb56d6a"
           role="tabpanel" aria-labelledby="heading-31ecc0e65b4cd3e6b12577382bb56d6a">
        
        
          
          
  <div class="category-post-list">
    
    
  </div>

          
  
    
    
    
    <div class="category-sub row nomargin-x">
      <a class="category-subitem collapsed
          list-group-item category-item-action col-10 col-md-11 col-xm-11" title="开发经验"
        id="heading-bfd19ce0478d81a44ceb5a9a1aa94202" role="tab" data-toggle="collapse" href="#collapse-bfd19ce0478d81a44ceb5a9a1aa94202"
        aria-expanded="false"
      >
        开发经验
        <span class="list-group-count">(1)</span>
        <i class="iconfont icon-arrowright"></i>
      </a>
      
      <div class="category-collapse collapse " id="collapse-bfd19ce0478d81a44ceb5a9a1aa94202"
           role="tabpanel" aria-labelledby="heading-bfd19ce0478d81a44ceb5a9a1aa94202">
        
        
          
  <div class="category-post-list">
    
    
      
      
        <a href="/deng-2022/blog_2/2023/09/10/Memory%20%E7%BC%98%E5%BF%86%E4%BA%A4%E5%8F%8B%E7%A4%BE%E5%8C%BA-%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3/" title="Memory 缘忆交友社区-开发文档"
           class="list-group-item list-group-item-action
           ">
          <span class="category-post">Memory 缘忆交友社区-开发文档</span>
        </a>
      
    
  </div>

        
      </div>
    </div>
  
        
      </div>
    </div>
  
        
      </div>
    </div>
  
        
      </div>
    </div>
  
</div>


  </aside>


    </div>

    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">揭秘 Elasticsearch 的神奇能力：从数据搜索到实时分析的终极指南</h1>
            
              <p class="note note-success">
                
                  
                    本文最后更新于：6 个月前
                  
                
              </p>
            
            
              <div class="markdown-body">
                
                <h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><ul>
<li>我很荣幸能够分享一篇关于 Elasticsearch 的博客笔记，<strong>部分正文内容</strong>转载自<strong>黑马程序员的优质笔记</strong></li>
<li>该笔记在该博文的<strong>正文</strong>栏目，在正文之前，是我在实<strong>际使用ES的过程</strong>中，所做的<strong>相关经验分享</strong></li>
</ul>
<h1 id="正文"><a href="#正文" class="headerlink" title="正文"></a>正文</h1><h2 id="经验分享"><a href="#经验分享" class="headerlink" title="经验分享"></a>经验分享</h2><h3 id="分词器"><a href="#分词器" class="headerlink" title="分词器"></a>分词器</h3><ul>
<li><h5 id="分词器是干啥用的？指定了分词的规则（2023-09-20午）"><a href="#分词器是干啥用的？指定了分词的规则（2023-09-20午）" class="headerlink" title="分词器是干啥用的？指定了分词的规则（2023/09/20午）"></a>分词器是干啥用的？指定了分词的规则（2023/09/20午）</h5></li>
</ul>
<h4 id="内置分词器"><a href="#内置分词器" class="headerlink" title="内置分词器"></a>内置分词器</h4><ul>
<li><h5 id="https-www-elastic-co-guide-en-elasticsearch-reference-7-17-analysis-analyzers-html"><a href="#https-www-elastic-co-guide-en-elasticsearch-reference-7-17-analysis-analyzers-html" class="headerlink" title="https://www.elastic.co/guide/en/elasticsearch/reference/7.17/analysis-analyzers.html"></a><a target="_blank" rel="noopener" href="https://www.elastic.co/guide/en/elasticsearch/reference/7.17/analysis-analyzers.html">https://www.elastic.co/guide/en/elasticsearch/reference/7.17/analysis-analyzers.html</a></h5></li>
<li><h5 id="了解一下，丰富的分词规则"><a href="#了解一下，丰富的分词规则" class="headerlink" title="了解一下，丰富的分词规则"></a>了解一下，丰富的分词规则</h5></li>
</ul>
<h4 id="空格分词器"><a href="#空格分词器" class="headerlink" title="空格分词器"></a>空格分词器</h4><ul>
<li>whitespace，按空格分词</li>
</ul>
<figure class="highlight fsharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs fsharp">POST <span class="hljs-keyword">_analyze</span><br>&#123;<br>  <span class="hljs-string">&quot;analyzer&quot;</span><span class="hljs-operator">:</span> <span class="hljs-string">&quot;whitespace&quot;</span>,<br>  <span class="hljs-string">&quot;text&quot;</span><span class="hljs-operator">:</span>     <span class="hljs-string">&quot;The quick brown fox.&quot;</span><br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="关键词分词器"><a href="#关键词分词器" class="headerlink" title="关键词分词器"></a>关键词分词器</h4><ul>
<li><h5 id="就是不分词，整句话当作一个专业术语"><a href="#就是不分词，整句话当作一个专业术语" class="headerlink" title="就是不分词，整句话当作一个专业术语"></a>就是不分词，整句话当作一个专业术语</h5></li>
</ul>
<h4 id="标准分词规则"><a href="#标准分词规则" class="headerlink" title="标准分词规则"></a>标准分词规则</h4><figure class="highlight fsharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs fsharp">POST <span class="hljs-keyword">_analyze</span><br>&#123;<br>  <span class="hljs-string">&quot;tokenizer&quot;</span><span class="hljs-operator">:</span> <span class="hljs-string">&quot;standard&quot;</span>,<br>  <span class="hljs-string">&quot;filter&quot;</span><span class="hljs-operator">:</span>  [ <span class="hljs-string">&quot;lowercase&quot;</span>, <span class="hljs-string">&quot;asciifolding&quot;</span> ],<br>  <span class="hljs-string">&quot;text&quot;</span><span class="hljs-operator">:</span>      <span class="hljs-string">&quot;Is this déja vu?&quot;</span><br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="分词器-analyze-和分词规则-tokenizer-有什么区别呢？"><a href="#分词器-analyze-和分词规则-tokenizer-有什么区别呢？" class="headerlink" title="分词器 analyze 和分词规则 tokenizer 有什么区别呢？"></a>分词器 analyze 和分词规则 tokenizer 有什么区别呢？</h5></li>
</ul>
<figure class="highlight coq"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs coq">在搜索引擎和文本分析领域中，分词器（Analyzer）和分词规则器（Tokenizer）是两个不同的概念。<br><br>分词器（Analyzer）是一种将文本转换为单词（<span class="hljs-keyword">Term</span>）序列的工具。它通常包含多个处理步骤，例如词法分析、去除停用词、小写转换、词干提取等。分词器的作用是将原始的文本输入转换为可供索引和搜索的标记流。例如，在Elasticsearch中，分词器被用于预处理文本数据并将其存储在倒排索引中，以支持全文搜索。<br><br>分词规则器（Tokenizer）是分词器的一个组成部分。它是文本分析的第一个处理步骤，将输入的文本按照指定的规则拆分为单词。常见的分词规则器有基于空格拆分的空格分词器、基于标点符号拆分的标点分词器等。分词规则器负责定义文本拆分的方式，决定了哪些字符会被视为词条的分隔。<br><br>总结来说，分词规则器（Tokenizer）是分词器（Analyzer）的组成部分，用于定义文本的拆分方式；而分词器（Analyzer）则包含多个处理步骤，用于将输入文本转换为标记流。<br></code></pre></td></tr></table></figure>

<ul>
<li><p>了解到这些分词器<strong>对中文不友好</strong>，我们需要下载 <strong>IK 分词器</strong> 插件，对<strong>中文分词更加友好</strong>，内置两种分词器</p>
<ul>
<li><h5 id="ik-smart"><a href="#ik-smart" class="headerlink" title="ik_smart"></a>ik_smart</h5></li>
<li><h5 id="ik-max-word"><a href="#ik-max-word" class="headerlink" title="ik_max_word"></a>ik_max_word</h5></li>
</ul>
</li>
</ul>
<h3 id="IK分词器（ES内置插件）"><a href="#IK分词器（ES内置插件）" class="headerlink" title="IK分词器（ES内置插件）"></a>IK分词器（ES内置插件）</h3><h4 id="下载安装"><a href="#下载安装" class="headerlink" title="下载安装"></a>下载安装</h4><ul>
<li><h5 id="7-·-Releases-·-medcl-elasticsearch-analysis-ik-github-com"><a href="#7-·-Releases-·-medcl-elasticsearch-analysis-ik-github-com" class="headerlink" title="7. · Releases · medcl/elasticsearch-analysis-ik (github.com)"></a><a target="_blank" rel="noopener" href="https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v7.17.7">7. · Releases · medcl/elasticsearch-analysis-ik (github.com)</a></h5></li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20230920115244986.png" alt="image-20230920115244986"></p>
<ul>
<li>下载完成，将压缩包解压在 Elasticsearch 的 <strong>plugins / ik目录下即可</strong> </li>
</ul>
<h4 id="修改版本一致"><a href="#修改版本一致" class="headerlink" title="修改版本一致"></a>修改版本一致</h4><ul>
<li><p>解压完成后，修改plugins / ik目录下的 <strong>plugin-descriptor.properties 文件</strong>，将 ik 版本<strong>修改为与 ES 版本一致</strong></p>
<ul>
<li><h5 id="注意：我使用的-ES-版本为-7-17-13，而-ik-版本为-7-17-7（2023-09-20午）"><a href="#注意：我使用的-ES-版本为-7-17-13，而-ik-版本为-7-17-7（2023-09-20午）" class="headerlink" title="注意：我使用的 ES 版本为 7.17.13，而 ik 版本为 7.17.7（2023/09/20午）"></a>注意：我使用的 ES 版本为 7.17.13，而 ik 版本为 7.17.7（2023/09/20午）</h5></li>
<li><p>可能会由于<strong>版本不兼容</strong>，而造成 ES 启动失败，所以需要更改 ik 版本</p>
</li>
</ul>
</li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20230920115558421.png" alt="image-20230920115558421"></p>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20230920113332061.png" alt="image-20230920113332061"></p>
<h4 id="启动ES、Kibana"><a href="#启动ES、Kibana" class="headerlink" title="启动ES、Kibana"></a>启动ES、Kibana</h4><ul>
<li><h5 id="启动成功："><a href="#启动成功：" class="headerlink" title="启动成功："></a>启动成功：</h5></li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20230920120124225.png" alt="image-20230920120124225"></p>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20230920120158428.png" alt="image-20230920120158428"></p>
<h4 id="测试分词效果"><a href="#测试分词效果" class="headerlink" title="测试分词效果"></a>测试分词效果</h4><p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20230920120416495.png" alt="image-20230920120416495"></p>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20230920120422210.png" alt="image-20230920120422210"></p>
<ul>
<li><h5 id="测试成功，这里也能看出来-ik-smart-和-ik-max-word-这两种不同分词模式的区别了（2023-09-20午）"><a href="#测试成功，这里也能看出来-ik-smart-和-ik-max-word-这两种不同分词模式的区别了（2023-09-20午）" class="headerlink" title="测试成功，这里也能看出来 ik_smart 和 ik_max_word 这两种不同分词模式的区别了（2023/09/20午）"></a>测试成功，这里也能看出来 ik_smart 和 ik_max_word 这两种不同分词模式的区别了（2023/09/20午）</h5><ul>
<li><code>ik_smart</code> 模式是 <strong>IK 分词器的简单模式</strong>，它会对文本进行<strong>较为粗粒度的切分</strong>，主要以将句子切分为一些较短的词语为目标，适用于<strong>快速搜索</strong>和一般文本处理场景。该模式下的分词结果倾向于保留短词</li>
<li><code>ik_max_word</code> 模式是 <strong>IK 分词器的细粒度模式</strong>，它会尽可能多地将<strong>文本切分为更小的词语</strong>，包括一些更细致的切分，如<strong>拆分复合词和词组</strong>等。该模式下的分词结果倾向于将文本切分为更多的词</li>
</ul>
</li>
</ul>
<h2 id="ES-调用方式"><a href="#ES-调用方式" class="headerlink" title="ES 调用方式"></a>ES 调用方式</h2><ul>
<li><h5 id="一般来讲，常见的有三种调用方式："><a href="#一般来讲，常见的有三种调用方式：" class="headerlink" title="一般来讲，常见的有三种调用方式："></a>一般来讲，常见的有三种调用方式：</h5><ul>
<li><p>HTTP Restful 调用</p>
</li>
<li><p>Kibana（Dev tools），本质上还是HTTP Restful 调用</p>
</li>
<li><h5 id="客户端调用：Java客户端、Go客户端"><a href="#客户端调用：Java客户端、Go客户端" class="headerlink" title="客户端调用：Java客户端、Go客户端"></a>客户端调用：Java客户端、Go客户端</h5></li>
</ul>
</li>
</ul>
<h3 id="Java-操作-ES"><a href="#Java-操作-ES" class="headerlink" title="Java 操作 ES"></a>Java 操作 ES</h3><ul>
<li><h5 id="一般来讲，也有三种方式："><a href="#一般来讲，也有三种方式：" class="headerlink" title="一般来讲，也有三种方式："></a>一般来讲，也有三种方式：</h5><ul>
<li>ES 官方的API：**[Introduction | Elasticsearch Java API Client <a target="_blank" rel="noopener" href="https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/7.17/introduction.html">7.17] | Elastic</a>**</li>
<li>ES以前的官方API：（已废弃，不建议用）</li>
<li><h5 id="Spring-Data-Elasticsearch（推荐）：Spring-Data-Elasticsearch-Reference-Documentation"><a href="#Spring-Data-Elasticsearch（推荐）：Spring-Data-Elasticsearch-Reference-Documentation" class="headerlink" title="Spring Data Elasticsearch（推荐）：Spring Data Elasticsearch - Reference Documentation"></a>Spring Data Elasticsearch（推荐）：<a target="_blank" rel="noopener" href="https://docs.spring.io/spring-data/elasticsearch/docs/4.4.10/reference/html/">Spring Data Elasticsearch - Reference Documentation</a></h5></li>
</ul>
</li>
<li><p>Spring-data系列：Spring 提供的操作数据的框架</p>
<ul>
<li>Spring-data-redis：操作redis的一套方法</li>
<li>Spring-data-mongodb：操作mongodb的一套方法</li>
<li>Spring-data-elasticsearch：操作elasticsearch的一套方法</li>
</ul>
</li>
</ul>
<h3 id="ES实现搜索接口"><a href="#ES实现搜索接口" class="headerlink" title="ES实现搜索接口"></a>ES实现搜索接口</h3><h4 id="建立索引"><a href="#建立索引" class="headerlink" title="建立索引"></a>建立索引</h4><ul>
<li><h5 id="在ES中，也存在和-MySQL类似的表结构，这里可以将二者对比一下："><a href="#在ES中，也存在和-MySQL类似的表结构，这里可以将二者对比一下：" class="headerlink" title="在ES中，也存在和 MySQL类似的表结构，这里可以将二者对比一下："></a>在ES中，也存在和 MySQL类似的表结构，这里可以将二者对比一下：</h5></li>
</ul>
<table>
<thead>
<tr>
<th><strong>MySQL</strong></th>
<th align="center"><strong>Elasticsearch</strong></th>
<th><strong>说明</strong></th>
</tr>
</thead>
<tbody><tr>
<td>Table</td>
<td align="center">Index</td>
<td>索引(index)，就是文档的集合，类似数据库的表(table)</td>
</tr>
<tr>
<td>Row</td>
<td align="center">Document</td>
<td>文档（Document），就是一条条的数据，类似数据库中的行（Row），文档都是JSON格式</td>
</tr>
<tr>
<td>Column</td>
<td align="center">Field</td>
<td>字段（Field），就是JSON文档中的字段，类似数据库中的列（Column）</td>
</tr>
<tr>
<td>Schema</td>
<td align="center">Mapping</td>
<td>Mapping（映射）是索引中文档的约束，例如字段类型约束。类似数据库的表结构（Schema）</td>
</tr>
<tr>
<td>SQL</td>
<td align="center">DSL</td>
<td>DSL是elasticsearch提供的JSON风格的请求语句，用来操作elasticsearch，实现CRUD</td>
</tr>
</tbody></table>
<ul>
<li><h5 id="数据库表："><a href="#数据库表：" class="headerlink" title="数据库表："></a>数据库表：</h5></li>
</ul>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> post<br>(<br>    id         <span class="hljs-type">bigint</span> auto_increment comment <span class="hljs-string">&#x27;id&#x27;</span><br>        <span class="hljs-keyword">primary</span> key,<br>    title      <span class="hljs-type">varchar</span>(<span class="hljs-number">512</span>)                       <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;标题&#x27;</span>,<br>    content    text                               <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;内容&#x27;</span>,<br>    tags       <span class="hljs-type">varchar</span>(<span class="hljs-number">1024</span>)                      <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;标签列表（json 数组）&#x27;</span>,<br>    thumbNum   <span class="hljs-type">int</span>      <span class="hljs-keyword">default</span> <span class="hljs-number">0</span>                 <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;点赞数&#x27;</span>,<br>    favourNum  <span class="hljs-type">int</span>      <span class="hljs-keyword">default</span> <span class="hljs-number">0</span>                 <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;收藏数&#x27;</span>,<br>    userId     <span class="hljs-type">bigint</span>                             <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;创建用户 id&#x27;</span>,<br>    createTime datetime <span class="hljs-keyword">default</span> <span class="hljs-built_in">CURRENT_TIMESTAMP</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;创建时间&#x27;</span>,<br>    updateTime datetime <span class="hljs-keyword">default</span> <span class="hljs-built_in">CURRENT_TIMESTAMP</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> <span class="hljs-keyword">on</span> <span class="hljs-keyword">update</span> <span class="hljs-built_in">CURRENT_TIMESTAMP</span> comment <span class="hljs-string">&#x27;更新时间&#x27;</span>,<br>    isDelete   tinyint  <span class="hljs-keyword">default</span> <span class="hljs-number">0</span>                 <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;是否删除&#x27;</span><br>)<br>    comment <span class="hljs-string">&#x27;帖子&#x27;</span> <span class="hljs-keyword">collate</span> <span class="hljs-operator">=</span> utf8mb4_unicode_ci;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="建立索引语句："><a href="#建立索引语句：" class="headerlink" title="建立索引语句："></a>建立索引语句：</h5></li>
<li><p>ES Mapping：</p>
</li>
<li><p>id（可以不放到字段设置里）</p>
</li>
<li><p>ES 中，尽量存放<strong>需要用户筛选</strong>（搜索）的数据</p>
</li>
<li><p><strong>aliases</strong>：别名（为了后续方便数据迁移）</p>
</li>
<li><p>字段类型是 text，这个字段是可被分词的、可模糊查询的；而如果是 keyword，只能完全匹配、精确查询。</p>
</li>
<li><p><strong>analyzer</strong>（存储时生效的分词器）：用 ik_max_word，拆的更碎、索引更多，更有可能被搜出来</p>
</li>
<li><p><strong>search_analyzer</strong>（查询时生效的分词器）：用 ik_smart，更偏向于用户想搜的分词</p>
</li>
<li><p>如果想要让 text 类型的分词字段也<strong>支持精确查询</strong>，可以创建 keyword 类型的子字段：</p>
</li>
</ul>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><code class="hljs css">POST post_v1<br>&#123;<br>&quot;aliases&quot;: &#123;<br>&quot;post&quot;: &#123;&#125;<br>&#125;,<br>&quot;mappings&quot;: &#123;<br>&quot;properties&quot;: &#123;<br>&quot;title&quot;: &#123;<br>&quot;type&quot;: <span class="hljs-string">&quot;text&quot;</span>,<br><span class="hljs-string">&quot;analyzer&quot;</span>: <span class="hljs-string">&quot;ik_max_word&quot;</span>,<br><span class="hljs-string">&quot;search_analyzer&quot;</span>: <span class="hljs-string">&quot;ik_smart&quot;</span>,<br><span class="hljs-string">&quot;fields&quot;</span>: &#123;<br>&quot;keyword&quot;: &#123;<br>&quot;type&quot;: <span class="hljs-string">&quot;keyword&quot;</span>,<br><span class="hljs-string">&quot;ignore_above&quot;</span>: <span class="hljs-number">256</span><br>&#125;<br>&#125;<br>&#125;,<br>&quot;<span class="hljs-attribute">content</span>&quot;: &#123;<br>&quot;type&quot;: <span class="hljs-string">&quot;text&quot;</span>,<br><span class="hljs-string">&quot;analyzer&quot;</span>: <span class="hljs-string">&quot;ik_max_word&quot;</span>,<br><span class="hljs-string">&quot;search_analyzer&quot;</span>: <span class="hljs-string">&quot;ik_smart&quot;</span>,<br><span class="hljs-string">&quot;fields&quot;</span>: &#123;<br>&quot;keyword&quot;: &#123;<br>&quot;type&quot;: <span class="hljs-string">&quot;keyword&quot;</span>,<br><span class="hljs-string">&quot;ignore_above&quot;</span>: <span class="hljs-number">256</span><br>&#125;<br>&#125;<br>&#125;,<br>&quot;tags&quot;: &#123;<br>&quot;type&quot;: <span class="hljs-string">&quot;keyword&quot;</span><br>&#125;,<br>&quot;userId&quot;: &#123;<br>&quot;type&quot;: <span class="hljs-string">&quot;keyword&quot;</span><br>&#125;,<br>&quot;createTime&quot;: &#123;<br>&quot;type&quot;: <span class="hljs-string">&quot;date&quot;</span><br>&#125;,<br>&quot;updateTime&quot;: &#123;<br>&quot;type&quot;: <span class="hljs-string">&quot;date&quot;</span><br>&#125;,<br>&quot;isDelete&quot;: &#123;<br>&quot;type&quot;: <span class="hljs-string">&quot;keyword&quot;</span><br>  &#125;<br>  &#125;<br> &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="SpringBoot项目中引入依赖："><a href="#SpringBoot项目中引入依赖：" class="headerlink" title="SpringBoot项目中引入依赖："></a>SpringBoot项目中引入依赖：</h5></li>
</ul>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>     <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>     <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-data-elasticsearch<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br> <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="开启ES相关配置："><a href="#开启ES相关配置：" class="headerlink" title="开启ES相关配置："></a>开启ES相关配置：</h5></li>
</ul>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">elasticsearch:</span><br>   <span class="hljs-attr">uris:</span> <span class="hljs-string">http://localhost:9200</span><br>   <span class="hljs-attr">username:</span> <span class="hljs-string">root</span><br>   <span class="hljs-attr">password:</span> <span class="hljs-number">123456</span><br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="索引结构映射："><a href="#索引结构映射：" class="headerlink" title="索引结构映射："></a>索引结构映射：</h5></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Document(indexName = &quot;post&quot;)</span><br><span class="hljs-meta">@Data</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">PostEsDTO</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">Serializable</span> &#123;<br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">String</span> <span class="hljs-variable">DATE_TIME_PATTERN</span> <span class="hljs-operator">=</span> <span class="hljs-string">&quot;yyyy-MM-dd&#x27;T&#x27;HH:mm:ss.SSS&#x27;Z&#x27;&quot;</span>;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * id</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-meta">@Id</span><br>    <span class="hljs-keyword">private</span> Long id;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 标题</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">private</span> String title;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 内容</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">private</span> String content;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 标签列表</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">private</span> List&lt;String&gt; tags;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 点赞数</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">private</span> Integer thumbNum;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 收藏数</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">private</span> Integer favourNum;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 创建用户 id</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">private</span> Long userId;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 创建时间</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-meta">@Field(index = false, store = true, type = FieldType.Date, format = &#123;&#125;, pattern = DATE_TIME_PATTERN)</span><br>    <span class="hljs-keyword">private</span> Date createTime;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 更新时间</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-meta">@Field(index = false, store = true, type = FieldType.Date, format = &#123;&#125;, pattern = DATE_TIME_PATTERN)</span><br>    <span class="hljs-keyword">private</span> Date updateTime;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 是否删除</span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">private</span> Integer isDelete;<br><br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">long</span> <span class="hljs-variable">serialVersionUID</span> <span class="hljs-operator">=</span> <span class="hljs-number">1L</span>;<br><br>    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">Gson</span> <span class="hljs-variable">GSON</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Gson</span>();<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 对象转包装类</span><br><span class="hljs-comment">     *</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> post</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> PostEsDTO <span class="hljs-title function_">objToDto</span><span class="hljs-params">(Post post)</span> &#123;<br>        <span class="hljs-keyword">if</span> (post == <span class="hljs-literal">null</span>) &#123;<br>            <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br>        &#125;<br>        <span class="hljs-type">PostEsDTO</span> <span class="hljs-variable">postEsDTO</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">PostEsDTO</span>();<br>        BeanUtils.copyProperties(post, postEsDTO);<br>        <span class="hljs-type">String</span> <span class="hljs-variable">tagsStr</span> <span class="hljs-operator">=</span> post.getTags();<br>        <span class="hljs-keyword">if</span> (StringUtils.isNotBlank(tagsStr)) &#123;<br>            postEsDTO.setTags(GSON.fromJson(tagsStr, <span class="hljs-keyword">new</span> <span class="hljs-title class_">TypeToken</span>&lt;List&lt;String&gt;&gt;() &#123;<br>            &#125;.getType()));<br>        &#125;<br>        <span class="hljs-keyword">return</span> postEsDTO;<br>    &#125;<br><br>    <span class="hljs-comment">/**</span><br><span class="hljs-comment">     * 包装类转对象</span><br><span class="hljs-comment">     *</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@param</span> postEsDTO</span><br><span class="hljs-comment">     * <span class="hljs-doctag">@return</span></span><br><span class="hljs-comment">     */</span><br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Post <span class="hljs-title function_">dtoToObj</span><span class="hljs-params">(PostEsDTO postEsDTO)</span> &#123;<br>        <span class="hljs-keyword">if</span> (postEsDTO == <span class="hljs-literal">null</span>) &#123;<br>            <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br>        &#125;<br>        <span class="hljs-type">Post</span> <span class="hljs-variable">post</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Post</span>();<br>        BeanUtils.copyProperties(postEsDTO, post);<br>        List&lt;String&gt; tagList = postEsDTO.getTags();<br>        <span class="hljs-keyword">if</span> (CollectionUtils.isNotEmpty(tagList)) &#123;<br>            post.setTags(GSON.toJson(tagList));<br>        &#125;<br>        <span class="hljs-keyword">return</span> post;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li>编写 DAO 层：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">interface</span> <span class="hljs-title class_">PostEsDao</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">ElasticsearchRepository</span>&lt;PostEsDTO, Long&gt; &#123;<br>    List&lt;PostEsDTO&gt; <span class="hljs-title function_">findByUserId</span><span class="hljs-params">(Long userId)</span>;<br>&#125;<br></code></pre></td></tr></table></figure>

<h4 id="增删改查"><a href="#增删改查" class="headerlink" title="增删改查"></a>增删改查</h4><ul>
<li>测试增删改查：</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Resource</span><br><span class="hljs-keyword">private</span> PostEsDao postEsDao;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 新增一条文档</span><br><span class="hljs-meta">@Test</span><br> <span class="hljs-keyword">void</span> <span class="hljs-title function_">testAdd</span><span class="hljs-params">()</span> &#123;<br>     <span class="hljs-type">PostEsDTO</span> <span class="hljs-variable">postEsDTO</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">PostEsDTO</span>();<br>     postEsDTO.setId(<span class="hljs-number">5L</span>);<br>     postEsDTO.setTitle(<span class="hljs-string">&quot;test&quot;</span>);<br>     postEsDTO.setContent(<span class="hljs-string">&quot;test&quot;</span>);<br>     postEsDTO.setTags(Arrays.asList(<span class="hljs-string">&quot;java&quot;</span>, <span class="hljs-string">&quot;python&quot;</span>));<br>     postEsDTO.setThumbNum(<span class="hljs-number">1</span>);<br>     postEsDTO.setFavourNum(<span class="hljs-number">1</span>);<br>     postEsDTO.setUserId(<span class="hljs-number">1L</span>);<br>     postEsDTO.setCreateTime(<span class="hljs-keyword">new</span> <span class="hljs-title class_">Date</span>());<br>     postEsDTO.setUpdateTime(<span class="hljs-keyword">new</span> <span class="hljs-title class_">Date</span>());<br>     postEsDTO.setIsDelete(<span class="hljs-number">0</span>);<br>     postEsDao.save(postEsDTO);<br>     System.out.println(postEsDTO.getId());<br> &#125;<br><br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 查找文档</span><br><span class="hljs-meta">@Test</span><br>  <span class="hljs-keyword">void</span> <span class="hljs-title function_">testFindById</span><span class="hljs-params">()</span> &#123;<br>      Optional&lt;PostEsDTO&gt; postEsDTO = postEsDao.findById(<span class="hljs-number">1L</span>);<br>      System.out.println(postEsDTO);<br>  &#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 查找所有文档</span><br><span class="hljs-meta">@Test</span><br>  <span class="hljs-keyword">void</span> <span class="hljs-title function_">testSelect</span><span class="hljs-params">()</span> &#123;<br>      System.out.println(postEsDao.count());<br>      Page&lt;PostEsDTO&gt; PostPage = postEsDao.findAll(<br>              PageRequest.of(<span class="hljs-number">0</span>, <span class="hljs-number">5</span>, Sort.by(<span class="hljs-string">&quot;createTime&quot;</span>)));<br>      List&lt;PostEsDTO&gt; postList = PostPage.getContent();<br>      System.out.println(postList);<br>  &#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="简单的增、删、改、查测试通过：（2023-09-20晚）"><a href="#简单的增、删、改、查测试通过：（2023-09-20晚）" class="headerlink" title="简单的增、删、改、查测试通过：（2023/09/20晚）"></a>简单的增、删、改、查测试通过：（2023/09/20晚）</h5></li>
</ul>
<p><img src="C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20230920172305509.png" alt="image-20230920172305509"></p>
<h4 id="DSL查询"><a href="#DSL查询" class="headerlink" title="DSL查询"></a>DSL查询</h4><ul>
<li><h5 id="参考文档："><a href="#参考文档：" class="headerlink" title="参考文档："></a>参考文档：</h5></li>
<li><h5 id="Query-and-filter-context-Elasticsearch-Guide-7-17-Elastic"><a href="#Query-and-filter-context-Elasticsearch-Guide-7-17-Elastic" class="headerlink" title="[Query and filter context | Elasticsearch Guide 7.17] | Elastic"></a>[Query and filter context | Elasticsearch Guide <a target="_blank" rel="noopener" href="https://www.elastic.co/guide/en/elasticsearch/reference/7.17/query-filter-context.html">7.17] | Elastic</a></h5></li>
<li><h5 id="Boolean-query-Elasticsearch-Guide-7-17-Elastic"><a href="#Boolean-query-Elasticsearch-Guide-7-17-Elastic" class="headerlink" title="[Boolean query | Elasticsearch Guide 7.17] | Elastic"></a>[Boolean query | Elasticsearch Guide <a target="_blank" rel="noopener" href="https://www.elastic.co/guide/en/elasticsearch/reference/7.17/query-dsl-bool-query.html">7.17] | Elastic</a></h5></li>
<li><h5 id="详细的DSL查询学习可以看官网学习，待我学成归来，就在此留下我的学习笔记（2023-09-21晚）"><a href="#详细的DSL查询学习可以看官网学习，待我学成归来，就在此留下我的学习笔记（2023-09-21晚）" class="headerlink" title="详细的DSL查询学习可以看官网学习，待我学成归来，就在此留下我的学习笔记（2023/09/21晚）"></a>详细的DSL查询学习可以看官网学习，待我学成归来，就在此留下我的学习笔记（2023/09/21晚）</h5></li>
</ul>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs awk">GET post/_search<br>&#123;<br> <span class="hljs-string">&quot;query&quot;</span>: &#123;<br> <span class="hljs-string">&quot;bool&quot;</span>: &#123; <span class="hljs-regexp">//</span> 组合条件<br> <span class="hljs-string">&quot;must&quot;</span>: [ <span class="hljs-regexp">//</span> 必须都满足<br> &#123; <span class="hljs-string">&quot;match&quot;</span>: &#123; <span class="hljs-string">&quot;title&quot;</span>: <span class="hljs-string">&quot;鱼皮&quot;</span> &#125;&#125;, <span class="hljs-regexp">//</span> match 模糊查询<br> &#123; <span class="hljs-string">&quot;match&quot;</span>: &#123; <span class="hljs-string">&quot;content&quot;</span>: <span class="hljs-string">&quot;知识星球&quot;</span> &#125;&#125;<br> ],<br> <span class="hljs-string">&quot;filter&quot;</span>: [<br> &#123; <span class="hljs-string">&quot;term&quot;</span>: &#123; <span class="hljs-string">&quot;status&quot;</span>: <span class="hljs-string">&quot;published&quot;</span> &#125;&#125;, <span class="hljs-regexp">//</span> term 精确查询<br> &#123; <span class="hljs-string">&quot;range&quot;</span>: &#123; <span class="hljs-string">&quot;publish_date&quot;</span>: &#123; <span class="hljs-string">&quot;gte&quot;</span>: <span class="hljs-string">&quot;2015-01-01&quot;</span> &#125;&#125;&#125; <span class="hljs-regexp">//</span> range 范围<br> ]<br> &#125;<br> &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="建议先测试，再翻译为Java客户端操作"><a href="#建议先测试，再翻译为Java客户端操作" class="headerlink" title="建议先测试，再翻译为Java客户端操作"></a>建议先测试，再翻译为Java客户端操作</h5></li>
</ul>
<h2 id="数据同步"><a href="#数据同步" class="headerlink" title="数据同步"></a>数据同步</h2><ul>
<li><p>一般情况下，如果做<strong>查询搜索</strong>功能，使用 ES 来<strong>模糊搜索</strong> <strong>（2023/09/21晚）</strong></p>
</li>
<li><p>但是数据是存放在数据库 <strong>MySQL</strong> 里 的，所以说我们需要把 <strong>MySQL 中的数据和 ES 进行同步</strong>，保证<strong>数据一致</strong>（以 MySQL 为主）</p>
</li>
<li><h5 id="MySQL-gt-ES-（单向）"><a href="#MySQL-gt-ES-（单向）" class="headerlink" title="MySQL =&gt; ES （单向）"></a>MySQL =&gt; ES （单向）</h5></li>
<li><p>首次安装完 ES，把 MySQL 数据全量同步到 ES 里，写一个单次脚本 4 种方式，全量同步（首次）+ 增量同步（新数据）：</p>
<ul>
<li><p><strong>定时任务</strong>：比如 1 分钟 1 次，找到 MySQL 中过去几分钟内（至少是定时周期的 2 倍）发 生改变的数据，然后更新到 ES。 </p>
<ul>
<li>优点：简单易懂、占用资源少、不用引入第三方中间件 </li>
<li>缺点：有时间差 应用场景：数据短时间内不同步影响不大、或者数据几乎不发生修改 </li>
</ul>
</li>
<li><p><strong>双写</strong>：写数据的时候，必须也去写 ES；更新删除数据库同理。</p>
<ul>
<li>事务：建议先保证  MySQL 写成功</li>
<li>如果 ES 写失败了，可以通过定时任务 + 日志 + 告警进行检测和修复 （补偿）</li>
</ul>
</li>
<li><p><strong>Logstash 数据同步管道</strong>：（一般要配合 kafka 消息队列 + beats 采集器）</p>
</li>
<li><p><strong>Canal 监听 MySQL Binlog</strong>：实时同步 </p>
</li>
</ul>
</li>
</ul>
<h3 id="Logstash"><a href="#Logstash" class="headerlink" title="Logstash"></a>Logstash</h3><ul>
<li><h5 id="Getting-Started-with-Logstash-Logstash-Reference-7-17-Elastic（2023-09-22晚）"><a href="#Getting-Started-with-Logstash-Logstash-Reference-7-17-Elastic（2023-09-22晚）" class="headerlink" title="[Getting Started with Logstash | Logstash Reference 7.17] | Elastic（2023/09/22晚）"></a>[Getting Started with Logstash | Logstash Reference <a target="_blank" rel="noopener" href="https://www.elastic.co/guide/en/logstash/7.17/getting-started-with-logstash.html">7.17] | Elastic</a>（2023/09/22晚）</h5></li>
<li><h5 id="Running-Logstash-on-Windows-Logstash-Reference-7-17-Elastic"><a href="#Running-Logstash-on-Windows-Logstash-Reference-7-17-Elastic" class="headerlink" title="[Running Logstash on Windows | Logstash Reference 7.17] | Elastic"></a>[Running Logstash on Windows | Logstash Reference <a target="_blank" rel="noopener" href="https://www.elastic.co/guide/en/logstash/7.17/running-logstash-windows.html">7.17] | Elastic</a></h5></li>
<li><p><strong>传输</strong> 和 <strong>处理 数据</strong>的管道</p>
<ul>
<li>好处：用起来方便，插件多 </li>
<li>缺点：成本更大、一般要配合其他组件使用（比如 kafka）</li>
</ul>
</li>
<li><p>本质上就是把<strong>编程式同步改为配置式同步</strong>，更加方便快捷</p>
</li>
</ul>
<h4 id="下载安装-1"><a href="#下载安装-1" class="headerlink" title="下载安装"></a>下载安装</h4><ul>
<li><h5 id="Download-Logstash-Free-Get-Started-Now-Elastic"><a href="#Download-Logstash-Free-Get-Started-Now-Elastic" class="headerlink" title="Download Logstash Free | Get Started Now | Elastic"></a><a target="_blank" rel="noopener" href="https://www.elastic.co/cn/downloads/logstash">Download Logstash Free | Get Started Now | Elastic</a></h5></li>
</ul>
<h4 id="demo测试"><a href="#demo测试" class="headerlink" title="demo测试"></a>demo测试</h4><ul>
<li><h5 id="Stashing-Your-First-Event-Logstash-Reference-7-17-Elastic"><a href="#Stashing-Your-First-Event-Logstash-Reference-7-17-Elastic" class="headerlink" title="[Stashing Your First Event | Logstash Reference 7.17] | Elastic"></a>[Stashing Your First Event | Logstash Reference <a target="_blank" rel="noopener" href="https://www.elastic.co/guide/en/logstash/7.17/first-event.html">7.17] | Elastic</a></h5></li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20230922205535009.png" alt="image-20230922205535009"></p>
<ul>
<li><h5 id="我们根据官网指引，可以找到这么一段测试代码："><a href="#我们根据官网指引，可以找到这么一段测试代码：" class="headerlink" title="我们根据官网指引，可以找到这么一段测试代码："></a>我们根据官网指引，可以找到这么一段测试代码：</h5></li>
</ul>
<figure class="highlight dust"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs dust"><span class="language-xml">logstash.bat -e &quot;input </span><span class="hljs-template-variable">&#123; stdin &#123; &#125;</span><span class="language-xml"> &#125; output </span><span class="hljs-template-variable">&#123; stdout &#123;&#125;</span><span class="language-xml"> &#125;&quot;</span><br></code></pre></td></tr></table></figure>

<ul>
<li><p>在<strong>bin目录下</strong>执行这段代码（可以理解为：指定输入输出<strong>配置均为默认</strong>，<strong>开启 Logstash</strong>）</p>
</li>
<li><h5 id="待启动完成后，随便输入内容，如果在命令行中有返回相同内容，则测试成功"><a href="#待启动完成后，随便输入内容，如果在命令行中有返回相同内容，则测试成功" class="headerlink" title="待启动完成后，随便输入内容，如果在命令行中有返回相同内容，则测试成功"></a>待启动完成后，随便输入内容，如果在命令行中有返回相同内容，则测试成功</h5></li>
<li><p>如图所示：</p>
</li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20230922205958186.png" alt="image-20230922205958186"></p>
<h4 id="自定义配置"><a href="#自定义配置" class="headerlink" title="自定义配置"></a>自定义配置</h4><ul>
<li><h5 id="快速开始：-Running-Logstash-on-Windows-Logstash-Reference-7-17-Elastic（2023-09-22晚）"><a href="#快速开始：-Running-Logstash-on-Windows-Logstash-Reference-7-17-Elastic（2023-09-22晚）" class="headerlink" title="快速开始：[Running Logstash on Windows | Logstash Reference 7.17] | Elastic（2023/09/22晚）"></a>快速开始：[Running Logstash on Windows | Logstash Reference <a target="_blank" rel="noopener" href="https://www.elastic.co/guide/en/logstash/7.17/running-logstash-windows.html">7.17] | Elastic</a>（2023/09/22晚）</h5></li>
<li><p>在官方文档中，找到这一段简单的示例配置：</p>
</li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20230922210307761.png" alt="image-20230922210307761"></p>
<ul>
<li>将这段配置粘贴进 <strong>config 下</strong>的 <strong>logstash-sample.conf 配置文件（可以保留该原文件，复制一份重命名）</strong>中：</li>
<li>这几行配置是干什么的呢？简单来讲就是<strong>定义了输入和输出</strong>：<strong>监听 UDP，并输出</strong></li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20230922210525309.png" alt="image-20230922210525309"></p>
<ul>
<li>按官方文档的操作来，尝试<strong>加载这个配置文件</strong> 并 <strong>启动 Logstash</strong>：</li>
</ul>
<figure class="highlight livescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs livescript">.<span class="hljs-string">\bin\logstash.bat</span> -f .<span class="hljs-string">\config\myTask.conf</span><br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="Running-Logstash-on-Windows-Logstash-Reference-7-17-Elastic-1"><a href="#Running-Logstash-on-Windows-Logstash-Reference-7-17-Elastic-1" class="headerlink" title="[Running Logstash on Windows | Logstash Reference 7.17] | Elastic"></a>[Running Logstash on Windows | Logstash Reference <a target="_blank" rel="noopener" href="https://www.elastic.co/guide/en/logstash/7.17/running-logstash-windows.html#running-logstash-windows-manual">7.17] | Elastic</a></h5></li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20230922211016754.png" alt="image-20230922211016754"></p>
<ul>
<li><h5 id="运行这行命令，可以看到-Logstash-成功启动运行了"><a href="#运行这行命令，可以看到-Logstash-成功启动运行了" class="headerlink" title="运行这行命令，可以看到 Logstash 成功启动运行了"></a>运行这行命令，可以看到 Logstash 成功启动运行了</h5></li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20230922211330283.png" alt="image-20230922211330283"></p>
<h4 id="同步MySQL"><a href="#同步MySQL" class="headerlink" title="同步MySQL"></a>同步MySQL</h4><ul>
<li><h5 id="Jdbc-input-plugin-Logstash-Reference-7-17-Elastic"><a href="#Jdbc-input-plugin-Logstash-Reference-7-17-Elastic" class="headerlink" title="[Jdbc input plugin | Logstash Reference 7.17] | Elastic"></a>[Jdbc input plugin | Logstash Reference <a target="_blank" rel="noopener" href="https://www.elastic.co/guide/en/logstash/7.17/plugins-inputs-jdbc.html">7.17] | Elastic</a></h5></li>
<li><h5 id="在官方文档中，找到这段配置，用来把-input输入与-MySQL数据库中的数据同步（2023-09-22晚）"><a href="#在官方文档中，找到这段配置，用来把-input输入与-MySQL数据库中的数据同步（2023-09-22晚）" class="headerlink" title="在官方文档中，找到这段配置，用来把 input输入与 MySQL数据库中的数据同步（2023/09/22晚）"></a>在官方文档中，找到这段配置，用来把 input输入与 MySQL数据库中的数据同步（2023/09/22晚）</h5></li>
</ul>
<figure class="highlight puppet"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs puppet"><span class="hljs-keyword">input</span> &#123;<br>  jdbc &#123;<br>    <span class="hljs-attr">jdbc_driver_library</span> =&gt; <span class="hljs-string">&quot;mysql-connector-java-5.1.36-bin.jar&quot;</span><br>    <span class="hljs-attr">jdbc_driver_class</span> =&gt; <span class="hljs-string">&quot;com.mysql.jdbc.Driver&quot;</span><br>    <span class="hljs-attr">jdbc_connection_string</span> =&gt; <span class="hljs-string">&quot;jdbc:mysql://localhost:3306/mydb&quot;</span><br>    <span class="hljs-attr">jdbc_user</span> =&gt; <span class="hljs-string">&quot;mysql&quot;</span><br>    <span class="hljs-attr">parameters</span> =&gt; &#123; <span class="hljs-string">&quot;favorite_artist&quot;</span> =&gt; <span class="hljs-string">&quot;Beethoven&quot;</span> &#125;<br>    <span class="hljs-keyword">schedule</span> =&gt; <span class="hljs-string">&quot;* * * * *&quot;</span><br>    statement =&gt; <span class="hljs-string">&quot;SELECT * from songs where artist = :favorite_artist&quot;</span><br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><p>这些配置是不是很眼熟？我们简单说明一下：</p>
<ul>
<li><strong>jdbc_driver_library</strong>：就是加载 MySQL 数据库的 jar 包（依赖）</li>
<li>接下来的四行配置不用多说，连接<strong>MySQL的驱动</strong>、<strong>对应数据库</strong>、<strong>用户名</strong>、<strong>密码</strong></li>
<li><strong>statement</strong>：SQL表达式，用来从 MySQL 中获取数据</li>
<li><strong>parameters</strong>：起到动态配置 SQL 语句中的参数的作用</li>
<li><strong>schedule</strong>：Cron表达式，实现定时查询</li>
</ul>
</li>
<li><h5 id="我们按自己实际的的需求，可以简单地修改配置"><a href="#我们按自己实际的的需求，可以简单地修改配置" class="headerlink" title="我们按自己实际的的需求，可以简单地修改配置"></a>我们按自己实际的的需求，可以简单地修改配置</h5></li>
<li><p>当然了，如果我们我们现在加载此配置、启动 Logstash，一定会报错，如图所示：</p>
</li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20230922213346119.png" alt="image-20230922213346119"></p>
<ul>
<li><h5 id="原因很简单，就是配置中的-mysql-jar包找不到，我们需要自己配置一个-mysql-jar包，并正确配置它的路径"><a href="#原因很简单，就是配置中的-mysql-jar包找不到，我们需要自己配置一个-mysql-jar包，并正确配置它的路径" class="headerlink" title="原因很简单，就是配置中的 mysql jar包找不到，我们需要自己配置一个 mysql jar包，并正确配置它的路径"></a>原因很简单，就是配置中的 mysql jar包找不到，我们需要自己配置一个 mysql jar包，并正确配置它的路径</h5></li>
<li><h5 id="这里有个技巧：在-IDEA-中找到项目所依赖的-jar-包"><a href="#这里有个技巧：在-IDEA-中找到项目所依赖的-jar-包" class="headerlink" title="这里有个技巧：在 IDEA 中找到项目所依赖的 jar 包"></a>这里有个技巧：在 IDEA 中找到项目所依赖的 jar 包</h5><ul>
<li>如图所示，选择对应的依赖后，可以直接在文件管理器中打开</li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20230922213029171.png" alt="image-20230922213029171"></p>
<ul>
<li>然后直接在文件管理器中复制，粘贴到 Logstash 目录下即可</li>
</ul>
</li>
<li><h5 id="加载配置、启动-Logstash，启动成功了："><a href="#加载配置、启动-Logstash，启动成功了：" class="headerlink" title="加载配置、启动 Logstash，启动成功了："></a>加载配置、启动 Logstash，启动成功了：</h5></li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20230922215626868.png" alt="image-20230922215626868"></p>
<ul>
<li><h5 id="聊聊我在这段配置上踩过的坑吧："><a href="#聊聊我在这段配置上踩过的坑吧：" class="headerlink" title="聊聊我在这段配置上踩过的坑吧："></a>聊聊我在这段配置上踩过的坑吧：</h5><ul>
<li>mysql jar 包路径外层多加了一层双引号</li>
<li>用户名、密码配置错误</li>
<li>SQL 语句中 where 多写了一个</li>
<li>timestamp 写成 timestampe</li>
</ul>
</li>
<li><h5 id="这段配置绝对不能出现任何问题，否则就会出现严重的报错。我的最终配置是这样的："><a href="#这段配置绝对不能出现任何问题，否则就会出现严重的报错。我的最终配置是这样的：" class="headerlink" title="这段配置绝对不能出现任何问题，否则就会出现严重的报错。我的最终配置是这样的："></a>这段配置绝对不能出现任何问题，否则就会出现严重的报错。我的最终配置是这样的：</h5></li>
</ul>
<figure class="highlight puppet"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs puppet"><span class="hljs-comment"># Sample Logstash configuration for receiving</span><br><span class="hljs-comment"># UDP syslog messages over port 514</span><br><br><span class="hljs-keyword">input</span> &#123;<br>  jdbc &#123;<br>    <span class="hljs-attr">jdbc_driver_library</span> =&gt; <span class="hljs-string">&quot;D:\softWare\logstash\logstash-7.17.9\config\mysql-connector-java-8.0.29.jar&quot;</span><br>    <span class="hljs-attr">jdbc_driver_class</span> =&gt; <span class="hljs-string">&quot;com.mysql.jdbc.Driver&quot;</span><br>    <span class="hljs-attr">jdbc_connection_string</span> =&gt; <span class="hljs-string">&quot;jdbc:mysql://localhost:3306/memory_search&quot;</span><br>    <span class="hljs-attr">jdbc_user</span> =&gt; <span class="hljs-string">&quot;root&quot;</span><br>    <span class="hljs-attr">jdbc_password</span> =&gt; <span class="hljs-string">&quot;Dw990831&quot;</span><br>    <span class="hljs-attr">statement</span> =&gt; <span class="hljs-string">&quot;SELECT * from post where 1 = 1&quot;</span><br>    <span class="hljs-attr">schedule</span> =&gt; <span class="hljs-string">&quot;*/5 * * * *&quot;</span><br>  &#125;<br>&#125;<br><br><span class="hljs-keyword">output</span> &#123;<br>  stdout &#123; <span class="hljs-attr">codec</span> =&gt; rubydebug &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><p>启动成功后，现在的 Logstash 是每5秒从数据库中同步所有数据（当然这是根据SQL语句来执行的），这数据量可能会很大</p>
<ul>
<li><h5 id="这就是全量同步了，我们不需要同步所有数据，我们可以选择同步最近更新的数据（2023-09-22晚）"><a href="#这就是全量同步了，我们不需要同步所有数据，我们可以选择同步最近更新的数据（2023-09-22晚）" class="headerlink" title="这就是全量同步了，我们不需要同步所有数据，我们可以选择同步最近更新的数据（2023/09/22晚）"></a>这就是全量同步了，我们不需要同步所有数据，我们可以选择同步最近更新的数据（2023/09/22晚）</h5></li>
</ul>
</li>
<li><p>添加如下配置：</p>
</li>
</ul>
<figure class="highlight ini"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs ini"><span class="hljs-attr">statement</span> =&gt; <span class="hljs-string">&quot;SELECT * from post where updateTime &gt; :sql_last_value&quot;</span><br><span class="hljs-attr">use_column_value</span> =&gt; <span class="hljs-literal">true</span><br><span class="hljs-attr">tracking_column_type</span> =&gt; <span class="hljs-string">&quot;timestamp&quot;</span><br><span class="hljs-attr">tracking_column</span> =&gt; <span class="hljs-string">&quot;updateTime&quot;</span><br><span class="hljs-attr">schedule</span> =&gt; <span class="hljs-string">&quot;*/5 * * * * *&quot;</span><br><span class="hljs-attr">jdbc_default_timezone</span> =&gt; <span class="hljs-string">&quot;Asia/Shanghai&quot;</span><br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="这段配置就是根据-updateTime-字段的最新值，同步updateTime-大于最新值的数据："><a href="#这段配置就是根据-updateTime-字段的最新值，同步updateTime-大于最新值的数据：" class="headerlink" title="这段配置就是根据 updateTime 字段的最新值，同步updateTime 大于最新值的数据："></a>这段配置就是根据 updateTime 字段的最新值，同步updateTime 大于最新值的数据：</h5></li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20230922224744313.png" alt="image-20230922224744313"></p>
<ul>
<li>所以说，<strong>sql_last_value 指定的是上次查到的数据的最后一行的指定字段</strong>，新的查询就是比较这个<strong>指定字段与sql_last_value的大小</strong></li>
<li>但是经过多次查询发现，这里的 <strong>sql_last_value 始终不变</strong><ul>
<li>我们可以在 data\plugins\inputs\jdbc\logstash_jdbc_last_run 看到 <strong>sql_last_value 指定的数据</strong>，确实没有变化：</li>
</ul>
</li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20230922230142159.png" alt="image-20230922230142159"></p>
<ul>
<li>将 tracking_column =&gt; “updateTime” 的 <strong>updateTime 修改为 updatetime</strong>，<strong>日期同步成功</strong></li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20230922225440159.png" alt="image-20230922225440159"></p>
<ul>
<li><h5 id="更新下数据库中的最新值，再看看效果，确实拿到了数据库中最新修改的值（参照上次修改后的最新值）："><a href="#更新下数据库中的最新值，再看看效果，确实拿到了数据库中最新修改的值（参照上次修改后的最新值）：" class="headerlink" title="更新下数据库中的最新值，再看看效果，确实拿到了数据库中最新修改的值（参照上次修改后的最新值）："></a>更新下数据库中的最新值，再看看效果，确实拿到了数据库中最新修改的值（参照上次修改后的最新值）：</h5></li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20230922230720711.png" alt="image-20230922230720711"></p>
<h4 id="同步ES"><a href="#同步ES" class="headerlink" title="同步ES"></a>同步ES</h4><ul>
<li><p>调试这么久，Logstash 能够<strong>正常同步 MySQL</strong> 了，接下来就是把同步到 input 的数据，<strong>同步到 ES</strong> 中了<strong>（2023/09/22晚）</strong></p>
</li>
<li><p>直接在官方文档中，找到输出 output 的相关配置：</p>
</li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20230923124744806.png" alt="image-20230923124744806"></p>
<ul>
<li>跟着官网简单的 demo 学就行，配置过一次就会了，这是我<strong>完成同步 ES 后的配置</strong>：（<strong>部分私密信息已做处理</strong>）</li>
</ul>
<figure class="highlight puppet"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><code class="hljs puppet"><span class="hljs-comment"># Sample Logstash configuration for receiving</span><br><span class="hljs-comment"># UDP syslog messages over port 514</span><br><br><span class="hljs-keyword">input</span> &#123;<br>  jdbc &#123;<br>    <span class="hljs-attr">jdbc_driver_library</span> =&gt; <span class="hljs-string">&quot;D:\softWare\logstash\logstash-7.17.9\config\mysql-connector-java-8.0.29.jar&quot;</span><br>    <span class="hljs-attr">jdbc_driver_class</span> =&gt; <span class="hljs-string">&quot;com.mysql.jdbc.Driver&quot;</span><br>    <span class="hljs-attr">jdbc_connection_string</span> =&gt; <span class="hljs-string">&quot;jdbc:mysql://localhost:3306/&quot;</span>******<span class="hljs-string">&quot;&quot;</span><br>    <span class="hljs-attr">jdbc_user</span> =&gt; <span class="hljs-string">&quot;******&quot;</span><br>    <span class="hljs-attr">jdbc_password</span> =&gt; <span class="hljs-string">&quot;&quot;</span>******<span class="hljs-string">&quot;&quot;</span><br>    <span class="hljs-attr">statement</span> =&gt; <span class="hljs-string">&quot;SELECT * from post where updateTime &gt; :sql_last_value&quot;</span><br>    <span class="hljs-attr">use_column_value</span> =&gt; <span class="hljs-keyword">true</span><br>    <span class="hljs-attr">tracking_column_type</span> =&gt; <span class="hljs-string">&quot;timestamp&quot;</span><br>    <span class="hljs-attr">tracking_column</span> =&gt; <span class="hljs-string">&quot;updatetime&quot;</span><br>    <span class="hljs-attr">schedule</span> =&gt; <span class="hljs-string">&quot;*/5 * * * * *&quot;</span><br>    <span class="hljs-attr">jdbc_default_timezone</span> =&gt; <span class="hljs-string">&quot;Asia/Shanghai&quot;</span><br>  &#125;<br>&#125;<br><br><span class="hljs-keyword">output</span> &#123;<br>  stdout &#123; <span class="hljs-attr">codec</span> =&gt; rubydebug &#125;<br><br>  <span class="hljs-keyword">elasticsearch</span> &#123;<br>    <span class="hljs-attr">hosts</span> =&gt; <span class="hljs-string">&quot;127.0.0.1:9200&quot;</span><br>    <span class="hljs-attr">index</span> =&gt; <span class="hljs-string">&quot;post_v1&quot;</span><br>    <span class="hljs-attr">document_id</span> =&gt; <span class="hljs-string">&quot;%&#123;id&#125;&quot;</span><br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="这里简单介绍下这几个配置的作用："><a href="#这里简单介绍下这几个配置的作用：" class="headerlink" title="这里简单介绍下这几个配置的作用："></a>这里简单介绍下这几个配置的作用：</h5><ul>
<li><strong>host</strong>：标识要进行同步的 ES 地址，即指定了：<strong>数据从 MySQL 中取出后，发送到哪</strong></li>
<li><strong>index</strong>：目标索引</li>
<li><strong>document_id</strong>：指定目标索引内，每一个文档的 id，就是<strong>从 SELECT * 中解构出 id 值</strong></li>
<li><strong>data_stream</strong>：特殊的数据格式，我们从数据库中取到的都是<strong>普通类型</strong>，<strong>不需要这行配置</strong></li>
</ul>
</li>
<li><p>其他的目前暂且不需要了解，日后再进一步学习</p>
</li>
<li><h5 id="加载配置，运行-Logstash，可以看到运行成功了，数据库中最新更新的数据也成功同步到了本地的-ES-上了："><a href="#加载配置，运行-Logstash，可以看到运行成功了，数据库中最新更新的数据也成功同步到了本地的-ES-上了：" class="headerlink" title="加载配置，运行 Logstash，可以看到运行成功了，数据库中最新更新的数据也成功同步到了本地的 ES 上了："></a>加载配置，运行 Logstash，可以看到运行成功了，数据库中最新更新的数据也成功同步到了本地的 ES 上了：</h5></li>
</ul>
<h5 id=""><a href="#" class="headerlink" title=""></a><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20230923125842246.png" alt="image-20230923125842246"></h5><ul>
<li><h5 id="从同步结果来看，我们还需要解决几个问题："><a href="#从同步结果来看，我们还需要解决几个问题：" class="headerlink" title="从同步结果来看，我们还需要解决几个问题："></a>从同步结果来看，我们还需要解决几个问题：</h5><ul>
<li>排除某些不需要同步的字段</li>
<li>ES 中同步过来的文档数据字段都是全小写，不是驼峰式</li>
<li>查询结果按 updateTime 降序排列，避免重排序，导致多同步了不必要的数据，造成性能浪费</li>
</ul>
</li>
<li><p>解决这三个问题当然很简单：</p>
<ul>
<li><h5 id="首先修改下-SQL-语句：（2023-09-23午）"><a href="#首先修改下-SQL-语句：（2023-09-23午）" class="headerlink" title="首先修改下 SQL 语句：（2023/09/23午）"></a>首先修改下 SQL 语句：（2023/09/23午）</h5></li>
</ul>
<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs n1ql">statement =&gt; &quot;<span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">from</span> post <span class="hljs-keyword">where</span> updateTime &gt; :sql_last_value <span class="hljs-keyword">and</span> updateTime &lt; now() <span class="hljs-keyword">order</span> <span class="hljs-keyword">by</span> updateTime <span class="hljs-keyword">desc</span><span class="hljs-string">&quot;</span><br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="再写入如下过滤配置，将对应字段进行驼峰式转换，并排除不需要的字段："><a href="#再写入如下过滤配置，将对应字段进行驼峰式转换，并排除不需要的字段：" class="headerlink" title="再写入如下过滤配置，将对应字段进行驼峰式转换，并排除不需要的字段："></a>再写入如下过滤配置，将对应字段进行驼峰式转换，并排除不需要的字段：</h5></li>
</ul>
<figure class="highlight coq"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs coq">filter &#123;<br>  mutate &#123;<br>    <span class="hljs-built_in">rename</span> =&gt; &#123;<br>      <span class="hljs-string">&quot;updatetime&quot;</span> =&gt; <span class="hljs-string">&quot;updateTime&quot;</span><br>      <span class="hljs-string">&quot;userid&quot;</span> =&gt; <span class="hljs-string">&quot;userId&quot;</span><br>      <span class="hljs-string">&quot;createtime&quot;</span> =&gt; <span class="hljs-string">&quot;createTime&quot;</span><br>      <span class="hljs-string">&quot;isdelete&quot;</span> =&gt; <span class="hljs-string">&quot;isDelete&quot;</span><br>    &#125;<br>    remove_field =&gt; [<span class="hljs-string">&quot;thumbnum&quot;</span>, <span class="hljs-string">&quot;favournum&quot;</span>]<br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure></li>
<li><p>重新进行同步，结果完美，顺利完成：</p>
</li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20230923144500259.png" alt="image-20230923144500259"></p>
<ul>
<li><h5 id="最后，Kibana-的数据面板也可以了解下"><a href="#最后，Kibana-的数据面板也可以了解下" class="headerlink" title="最后，Kibana 的数据面板也可以了解下"></a>最后，Kibana 的数据面板也可以了解下</h5></li>
</ul>
<h3 id="Logstash-配置多个输入-输出源（小丑的第一次尝试）"><a href="#Logstash-配置多个输入-输出源（小丑的第一次尝试）" class="headerlink" title="Logstash 配置多个输入 / 输出源（小丑的第一次尝试）"></a>Logstash 配置多个输入 / 输出源（小丑的第一次尝试）</h3><blockquote>
<p>🔥 最近在优化 Memory 聚合搜索平台，尝试实现博文 article 的快速搜索和关键词高亮显示等功能</p>
<h5 id="主要工作如下："><a href="#主要工作如下：" class="headerlink" title="主要工作如下："></a>主要工作如下：</h5><ul>
<li>新增 article 实体，<strong>表结构</strong>已给出 👇</li>
<li>新增博文的 <strong>ES 包装类</strong>（ArticleEsDao）、<strong>博文查询参数</strong>（ArticleQueryRequest）、<strong>博文高亮字段</strong>（ArticleEsHighlightData）</li>
<li>使用 <strong>Spring Data Elasticsearch</strong> 的 <strong>QueryBuilder 组合条件查询</strong>，实现使用 ES <strong>快速搜索博文</strong>和<strong>关键词高亮显示</strong></li>
<li>新增<strong>博文数据源接口</strong>（ArticleDataSource），供聚合搜索调用</li>
<li>配置 Logstash 实现 MySQL 和 ES <strong>数据同步</strong></li>
</ul>
</blockquote>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">-- 博文建表SQL语句</span><br><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> article<br>(<br>    id          <span class="hljs-type">bigint</span>                                 <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;文章id&#x27;</span>,<br>    title       <span class="hljs-type">varchar</span>(<span class="hljs-number">256</span>)                           <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;文章标题&#x27;</span>,<br>    description <span class="hljs-type">varchar</span>(<span class="hljs-number">256</span>)                           <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;文章摘要&#x27;</span>,<br>    content     <span class="hljs-type">varchar</span>(<span class="hljs-number">2048</span>)                          <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;文章内容&#x27;</span>,<br>    author_id   <span class="hljs-type">bigint</span>                                 <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;创作者&#x27;</span>,<br>    <span class="hljs-keyword">view</span>        <span class="hljs-type">int</span>          <span class="hljs-keyword">default</span> <span class="hljs-number">0</span>                 <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;浏览量&#x27;</span>,<br>    likes       <span class="hljs-type">int</span>          <span class="hljs-keyword">default</span> <span class="hljs-number">0</span>                 <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;点赞量&#x27;</span>,<br>    comments    <span class="hljs-type">varchar</span>(<span class="hljs-number">256</span>) <span class="hljs-keyword">default</span> <span class="hljs-string">&#x27;0&#x27;</span>               <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;评论量&#x27;</span>,<br>    create_time datetime     <span class="hljs-keyword">default</span> <span class="hljs-built_in">CURRENT_TIMESTAMP</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;创建时间&#x27;</span>,<br>    update_time datetime     <span class="hljs-keyword">default</span> <span class="hljs-built_in">CURRENT_TIMESTAMP</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> <span class="hljs-keyword">on</span> <span class="hljs-keyword">update</span> <span class="hljs-built_in">CURRENT_TIMESTAMP</span> comment <span class="hljs-string">&#x27;更新时间&#x27;</span>,<br>    is_delete   tinyint      <span class="hljs-keyword">default</span> <span class="hljs-number">0</span>                 <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;逻辑删除&#x27;</span>,<br>    collects    <span class="hljs-type">int</span>                                    <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;收藏量&#x27;</span>,<br>    article_url <span class="hljs-type">varchar</span>(<span class="hljs-number">2048</span>)                          <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;封面图片&#x27;</span>,<br>    tags        <span class="hljs-type">varchar</span>(<span class="hljs-number">256</span>)                           <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> comment <span class="hljs-string">&#x27;文章标签&#x27;</span><br>)<br>    comment <span class="hljs-string">&#x27;博文&#x27;</span>;<br></code></pre></td></tr></table></figure>

<h4 id="同步配置"><a href="#同步配置" class="headerlink" title="同步配置"></a>同步配置</h4><ul>
<li>新增 article 相关实体的过程这里先<strong>不细讲</strong>，重点记录：如何实现 MySQL 和 ES <strong>数据同步</strong></li>
<li>在 <strong>Logstash 的 config 目录</strong>下，我们作如下配置：<strong>（2023/11/07晚）</strong></li>
</ul>
<figure class="highlight puppet"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br></pre></td><td class="code"><pre><code class="hljs puppet"><span class="hljs-comment"># Sample Logstash configuration for receiving</span><br><span class="hljs-comment"># UDP syslog messages over port 514</span><br><br><span class="hljs-keyword">input</span> &#123;<br>  jdbc &#123;<br>    <span class="hljs-attr">jdbc_driver_library</span> =&gt; <span class="hljs-string">&quot;D:\softWare\logstash\logstash-7.17.9\config\mysql-connector-java-8.0.29.jar&quot;</span><br>    <span class="hljs-attr">jdbc_driver_class</span> =&gt; <span class="hljs-string">&quot;com.mysql.jdbc.Driver&quot;</span><br>    <span class="hljs-attr">jdbc_connection_string</span> =&gt; <span class="hljs-string">&quot;jdbc:mysql://localhost:3306/******&quot;</span><br>    <span class="hljs-attr">jdbc_user</span> =&gt; <span class="hljs-string">&quot;******&quot;</span><br>    <span class="hljs-attr">jdbc_password</span> =&gt; <span class="hljs-string">&quot;******&quot;</span><br>    <span class="hljs-attr">statement</span> =&gt; <span class="hljs-string">&quot;SELECT * from article where update_time &gt; :sql_last_value and update_time &lt; now() order by update_time desc&quot;</span><br>    <span class="hljs-attr">use_column_value</span> =&gt; <span class="hljs-keyword">true</span><br>    <span class="hljs-attr">tracking_column_type</span> =&gt; <span class="hljs-string">&quot;timestamp&quot;</span><br>    <span class="hljs-attr">tracking_column</span> =&gt; <span class="hljs-string">&quot;update_time&quot;</span><br>    <span class="hljs-attr">schedule</span> =&gt; <span class="hljs-string">&quot;*/5 * * * * *&quot;</span><br>    <span class="hljs-attr">jdbc_default_timezone</span> =&gt; <span class="hljs-string">&quot;Asia/Shanghai&quot;</span><br>  &#125;<br>&#125;<br><br><span class="hljs-keyword">input</span> &#123;<br>  jdbc &#123;<br>    <span class="hljs-attr">jdbc_driver_library</span> =&gt; <span class="hljs-string">&quot;D:\softWare\logstash\logstash-7.17.9\config\mysql-connector-java-8.0.29.jar&quot;</span><br>    <span class="hljs-attr">jdbc_driver_class</span> =&gt; <span class="hljs-string">&quot;com.mysql.jdbc.Driver&quot;</span><br>    <span class="hljs-attr">jdbc_connection_string</span> =&gt; <span class="hljs-string">&quot;jdbc:mysql://localhost:3306/******&quot;</span><br>    <span class="hljs-attr">jdbc_user</span> =&gt; <span class="hljs-string">&quot;******&quot;</span><br>    <span class="hljs-attr">jdbc_password</span> =&gt; <span class="hljs-string">&quot;******&quot;</span><br>    <span class="hljs-attr">statement</span> =&gt; <span class="hljs-string">&quot;SELECT * from post where updateTime &gt; :sql_last_value and updateTime &lt; now() order by updateTime desc&quot;</span><br>    <span class="hljs-attr">use_column_value</span> =&gt; <span class="hljs-keyword">true</span><br>    <span class="hljs-attr">tracking_column_type</span> =&gt; <span class="hljs-string">&quot;timestamp&quot;</span><br>    <span class="hljs-attr">tracking_column</span> =&gt; <span class="hljs-string">&quot;updatetime&quot;</span><br>    <span class="hljs-attr">schedule</span> =&gt; <span class="hljs-string">&quot;*/5 * * * * *&quot;</span><br>    <span class="hljs-attr">jdbc_default_timezone</span> =&gt; <span class="hljs-string">&quot;Asia/Shanghai&quot;</span><br>  &#125;<br>&#125;<br><br><span class="hljs-keyword">filter</span> &#123;<br>  mutate &#123;<br>    <span class="hljs-attr">rename</span> =&gt; &#123;<br>      <span class="hljs-string">&quot;updatetime&quot;</span> =&gt; <span class="hljs-string">&quot;updateTime&quot;</span><br>      <span class="hljs-string">&quot;userid&quot;</span> =&gt; <span class="hljs-string">&quot;userId&quot;</span><br>      <span class="hljs-string">&quot;createtime&quot;</span> =&gt; <span class="hljs-string">&quot;createTime&quot;</span><br>      <span class="hljs-string">&quot;isdelete&quot;</span> =&gt; <span class="hljs-string">&quot;isDelete&quot;</span><br>    &#125;<br>    <span class="hljs-keyword">remove_field</span> =&gt; [<span class="hljs-string">&quot;thumbnum&quot;</span>, <span class="hljs-string">&quot;favournum&quot;</span>]<br>  &#125;<br>&#125;<br><br><span class="hljs-keyword">output</span> &#123;<br>  stdout &#123; <span class="hljs-attr">codec</span> =&gt; rubydebug &#125;<br><br>  <span class="hljs-keyword">elasticsearch</span> &#123;<br>    <span class="hljs-attr">hosts</span> =&gt; <span class="hljs-string">&quot;127.0.0.1:9200&quot;</span><br>    <span class="hljs-attr">index</span> =&gt; <span class="hljs-string">&quot;post_v1&quot;</span><br>    <span class="hljs-attr">document_id</span> =&gt; <span class="hljs-string">&quot;%&#123;id&#125;&quot;</span><br>  &#125;<br>&#125;<br><br><span class="hljs-keyword">output</span> &#123;<br>  stdout &#123; <span class="hljs-attr">codec</span> =&gt; rubydebug &#125;<br><br>  <span class="hljs-keyword">elasticsearch</span> &#123;  <br>    <span class="hljs-attr">hosts</span> =&gt; [<span class="hljs-string">&quot;localhost:9200&quot;</span>]  <br>    <span class="hljs-attr">index</span> =&gt; <span class="hljs-string">&quot;article_v1&quot;</span>  <br>    <span class="hljs-attr">document_id</span> =&gt; <span class="hljs-string">&quot;%&#123;id&#125;&quot;</span>  <br>  &#125;  <br>&#125;<br></code></pre></td></tr></table></figure>

<blockquote>
<h5 id="🥣-我们废话少说，看清楚如上配置-👆"><a href="#🥣-我们废话少说，看清楚如上配置-👆" class="headerlink" title="🥣 我们废话少说，看清楚如上配置 👆"></a>🥣 我们废话少说，看清楚如上配置 👆</h5><ul>
<li><p>如果想要指定多个数据源，就<strong>编写多个 input 块</strong></p>
</li>
<li><p>同样的，如果想要指定多个输出，那么就<strong>编写多个 output 块</strong></p>
</li>
</ul>
</blockquote>
<ul>
<li>比较有趣的是，新增的 <strong>article 实体</strong>的字段是<strong>下划线命名法</strong>，而 <strong>post 实体</strong>的字段却是<strong>驼峰命名法</strong>：</li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231107223434622.png" alt="image-20231107223434622"></p>
<ul>
<li>这样的属性名肯定是<strong>不规范的</strong>（当然，是因为 <strong>article 是我从 Memory 缘忆交友社区下直接粘贴过来的</strong>）</li>
<li>不过，正好可以比对下<strong>不同命名规范的属性</strong>，在 Logstash 配置中的写法区别了：<strong>（2023/11/07晚）</strong></li>
</ul>
<figure class="highlight puppet"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs puppet">-- 下划线命名法<br><span class="hljs-keyword">input</span> &#123;  <br>  jdbc &#123;<br>    <span class="hljs-attr">jdbc_driver_library</span> =&gt; <span class="hljs-string">&quot;D:\softWare\logstash\logstash-7.17.9\config\mysql-connector-java-8.0.29.jar&quot;</span><br>    <span class="hljs-attr">jdbc_driver_class</span> =&gt; <span class="hljs-string">&quot;com.mysql.jdbc.Driver&quot;</span><br>    <span class="hljs-attr">jdbc_connection_string</span> =&gt; <span class="hljs-string">&quot;jdbc:mysql://localhost:3306/******&quot;</span><br>    <span class="hljs-attr">jdbc_user</span> =&gt; <span class="hljs-string">&quot;******&quot;</span><br>    <span class="hljs-attr">jdbc_password</span> =&gt; <span class="hljs-string">&quot;******&quot;</span><br>    <span class="hljs-attr">statement</span> =&gt; <span class="hljs-string">&quot;SELECT * from article where update_time &gt; :sql_last_value and update_time &lt; now() order by update_time desc&quot;</span><br>    <span class="hljs-attr">use_column_value</span> =&gt; <span class="hljs-keyword">true</span><br>    <span class="hljs-attr">tracking_column_type</span> =&gt; <span class="hljs-string">&quot;timestamp&quot;</span><br>    <span class="hljs-attr">tracking_column</span> =&gt; <span class="hljs-string">&quot;update_time&quot;</span><br>    <span class="hljs-attr">schedule</span> =&gt; <span class="hljs-string">&quot;*/5 * * * * *&quot;</span><br>    <span class="hljs-attr">jdbc_default_timezone</span> =&gt; <span class="hljs-string">&quot;Asia/Shanghai&quot;</span><br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<figure class="highlight puppet"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs puppet">-- 驼峰命名法<br><span class="hljs-keyword">input</span> &#123;<br>  jdbc &#123;<br>    <span class="hljs-attr">jdbc_driver_library</span> =&gt; <span class="hljs-string">&quot;D:\softWare\logstash\logstash-7.17.9\config\mysql-connector-java-8.0.29.jar&quot;</span><br>    <span class="hljs-attr">jdbc_driver_class</span> =&gt; <span class="hljs-string">&quot;com.mysql.jdbc.Driver&quot;</span><br>    <span class="hljs-attr">jdbc_connection_string</span> =&gt; <span class="hljs-string">&quot;jdbc:mysql://localhost:3306/******&quot;</span><br>    <span class="hljs-attr">jdbc_user</span> =&gt; <span class="hljs-string">&quot;******&quot;</span><br>    <span class="hljs-attr">jdbc_password</span> =&gt; <span class="hljs-string">&quot;******&quot;</span><br>    <span class="hljs-attr">statement</span> =&gt; <span class="hljs-string">&quot;SELECT * from post where updateTime &gt; :sql_last_value and updateTime &lt; now() order by updateTime desc&quot;</span><br>    <span class="hljs-attr">use_column_value</span> =&gt; <span class="hljs-keyword">true</span><br>    <span class="hljs-attr">tracking_column_type</span> =&gt; <span class="hljs-string">&quot;timestamp&quot;</span><br>    <span class="hljs-attr">tracking_column</span> =&gt; <span class="hljs-string">&quot;updatetime&quot;</span><br>    <span class="hljs-attr">schedule</span> =&gt; <span class="hljs-string">&quot;*/5 * * * * *&quot;</span><br>    <span class="hljs-attr">jdbc_default_timezone</span> =&gt; <span class="hljs-string">&quot;Asia/Shanghai&quot;</span><br>  &#125;<br></code></pre></td></tr></table></figure>

<h4 id="ES-查询"><a href="#ES-查询" class="headerlink" title="ES 查询"></a>ES 查询</h4><ul>
<li>Logstash 同步配置写完之后，当然要进行测试了，看看数据是否成功从 MySQL 成功同步到了 ES 中</li>
<li>首先<strong>新增 ES 索引</strong>，在 <strong>Kibana 监控面板下</strong>，执行如下 DSL 语句：</li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs bash">PUT /article_v1  <br>&#123;  <br>  <span class="hljs-string">&quot;settings&quot;</span>: &#123;  <br>    <span class="hljs-string">&quot;number_of_shards&quot;</span>: 3,  <br>    <span class="hljs-string">&quot;number_of_replicas&quot;</span>: 2  <br>  &#125;  <br>&#125;<br></code></pre></td></tr></table></figure>

<blockquote>
<h5 id="🔥-注意："><a href="#🔥-注意：" class="headerlink" title="🔥 注意："></a>🔥 注意：</h5><ul>
<li><h5 id="索引名要跟-Logstash-配置中-output-块下的-index-属性对应："><a href="#索引名要跟-Logstash-配置中-output-块下的-index-属性对应：" class="headerlink" title="索引名要跟 Logstash 配置中 output 块下的 index 属性对应："></a>索引名要跟 Logstash 配置中 output 块下的 <code>index</code> 属性对应：</h5></li>
</ul>
<figure class="highlight abnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs abnf"><span class="hljs-attribute">index</span> <span class="hljs-operator">=</span>&gt; <span class="hljs-string">&quot;article_v1&quot;</span>  <br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="跟-ArticleEsDao-的-Document-字段对应："><a href="#跟-ArticleEsDao-的-Document-字段对应：" class="headerlink" title="跟 ArticleEsDao 的 Document 字段对应："></a>跟 ArticleEsDao 的 <code>Document</code> 字段对应：</h5></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Document(indexName = &quot;article_v1&quot;)</span><br></code></pre></td></tr></table></figure>
</blockquote>
<ul>
<li>按官方文档的操作来，尝试<strong>加载这个配置文件</strong> 并 <strong>启动 Logstash</strong>：</li>
</ul>
<figure class="highlight livescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs livescript">.<span class="hljs-string">\bin\logstash.bat</span> -f .<span class="hljs-string">\config\myTask.conf</span><br></code></pre></td></tr></table></figure>

<ul>
<li><strong>随便修改一条记录</strong>（下面的<code>实现 updateTime 字段自动更新</code>一栏中有提到，<strong>数据开始同步</strong> 👇：</li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231107225828473.png" alt="image-20231107225828473"></p>
<ul>
<li>在 <strong>Kibana 监控面板</strong>下，使用 DSL 语句<strong>执行查询</strong>，效果如下：</li>
</ul>
<figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs routeros"><span class="hljs-built_in">GET</span> article_v1/_search<br></code></pre></td></tr></table></figure>

<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231107221155736.png" alt="image-20231107221155736"></p>
<ul>
<li>成功完成 <code>article</code> 实体的<strong>数据同步</strong> <strong>（2023/11/07晚）</strong></li>
</ul>
<h4 id="实现-updateTime-字段自动更新"><a href="#实现-updateTime-字段自动更新" class="headerlink" title="实现 updateTime 字段自动更新"></a>实现 updateTime 字段自动更新</h4><ul>
<li>什么意思呢？我们希望在<strong>修改完数据库表中的记录</strong>后，该条记录<strong>对应的 uodateTime 字段</strong>实现<strong>自动更新</strong></li>
<li>实现方法很简单，在 IDEA 中，直接修改表的 updateTime 字段属性，如下：</li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231107224250849.png" alt="image-20231107224250849"></p>
<ul>
<li>对应的 <strong><code>DDL</code> 语句</strong>是这样的：</li>
</ul>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sql">updateTime datetime <span class="hljs-keyword">default</span> <span class="hljs-built_in">CURRENT_TIMESTAMP</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">null</span> <span class="hljs-keyword">on</span> <span class="hljs-keyword">update</span> <span class="hljs-built_in">CURRENT_TIMESTAMP</span> comment <span class="hljs-string">&#x27;更新时间&#x27;</span>,<br></code></pre></td></tr></table></figure>

<ul>
<li>这样，我们<strong>更新记录</strong>后，该记录 updateTime 字段会<strong>自动更新为最近修改时间</strong>：<strong>（2023/11/07晚）</strong></li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231107224550821.png" alt="image-20231107224550821"></p>
<h3 id="Logstash-配置多个输入输出源Ⅱ"><a href="#Logstash-配置多个输入输出源Ⅱ" class="headerlink" title="Logstash 配置多个输入输出源Ⅱ"></a>Logstash 配置多个输入输出源Ⅱ</h3><ul>
<li><p>如何配置多个 input 块和 output 块？很简单的问题，多写几个配置文件就可以了：</p>
</li>
<li><h5 id="myTask-conf："><a href="#myTask-conf：" class="headerlink" title="myTask.conf："></a><code>myTask.conf</code>：</h5></li>
</ul>
<figure class="highlight puppet"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><code class="hljs puppet"><span class="hljs-comment"># Sample Logstash configuration for receiving</span><br><span class="hljs-comment"># UDP syslog messages over port 514</span><br><br><span class="hljs-keyword">input</span> &#123;<br>  jdbc &#123;<br>    <span class="hljs-attr">jdbc_driver_library</span> =&gt; <span class="hljs-string">&quot;D:\softWare\logstash\logstash-7.17.9\config\mysql-connector-java-8.0.29.jar&quot;</span><br>    <span class="hljs-attr">jdbc_driver_class</span> =&gt; <span class="hljs-string">&quot;com.mysql.jdbc.Driver&quot;</span><br>    <span class="hljs-attr">jdbc_connection_string</span> =&gt; <span class="hljs-string">&quot;jdbc:mysql://localhost:3306/memory_search&quot;</span><br>    <span class="hljs-attr">jdbc_user</span> =&gt; <span class="hljs-string">&quot;root&quot;</span><br>    <span class="hljs-attr">jdbc_password</span> =&gt; <span class="hljs-string">&quot;Dw990831&quot;</span><br>    <span class="hljs-attr">statement</span> =&gt; <span class="hljs-string">&quot;SELECT * from post where updateTime &gt; :sql_last_value and updateTime &lt; now() order by updateTime desc&quot;</span><br>    <span class="hljs-attr">use_column_value</span> =&gt; <span class="hljs-keyword">true</span><br>    <span class="hljs-attr">tracking_column_type</span> =&gt; <span class="hljs-string">&quot;timestamp&quot;</span><br>    <span class="hljs-attr">tracking_column</span> =&gt; <span class="hljs-string">&quot;updatetime&quot;</span><br>    <span class="hljs-attr">schedule</span> =&gt; <span class="hljs-string">&quot;*/5 * * * * *&quot;</span><br>    <span class="hljs-attr">jdbc_default_timezone</span> =&gt; <span class="hljs-string">&quot;Asia/Shanghai&quot;</span><br>  &#125;<br>&#125;<br><br><span class="hljs-keyword">filter</span> &#123;<br>  mutate &#123;<br>    <span class="hljs-attr">rename</span> =&gt; &#123;<br>      <span class="hljs-string">&quot;updatetime&quot;</span> =&gt; <span class="hljs-string">&quot;updateTime&quot;</span><br>      <span class="hljs-string">&quot;userid&quot;</span> =&gt; <span class="hljs-string">&quot;userId&quot;</span><br>      <span class="hljs-string">&quot;createtime&quot;</span> =&gt; <span class="hljs-string">&quot;createTime&quot;</span><br>      <span class="hljs-string">&quot;isdelete&quot;</span> =&gt; <span class="hljs-string">&quot;isDelete&quot;</span><br>    &#125;<br>    <span class="hljs-keyword">remove_field</span> =&gt; [<span class="hljs-string">&quot;thumbnum&quot;</span>, <span class="hljs-string">&quot;favournum&quot;</span>]<br>  &#125;<br>&#125;<br><br><span class="hljs-keyword">output</span> &#123;<br>  stdout &#123; <span class="hljs-attr">codec</span> =&gt; rubydebug &#125;<br>    <span class="hljs-keyword">elasticsearch</span> &#123;<br>    <span class="hljs-attr">hosts</span> =&gt; <span class="hljs-string">&quot;127.0.0.1:9200&quot;</span><br>    <span class="hljs-attr">index</span> =&gt; <span class="hljs-string">&quot;post_v1&quot;</span><br>    <span class="hljs-attr">document_id</span> =&gt; <span class="hljs-string">&quot;%&#123;id&#125;&quot;</span><br>  &#125;<br>&#125;<br><br><br></code></pre></td></tr></table></figure>

<ul>
<li><code>myTask2.conf</code>：</li>
</ul>
<figure class="highlight puppet"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><code class="hljs puppet"><span class="hljs-keyword">input</span> &#123;<br>  jdbc &#123;<br>    <span class="hljs-attr">jdbc_driver_library</span> =&gt; <span class="hljs-string">&quot;D:\softWare\logstash\logstash-7.17.9\config\mysql-connector-java-8.0.29.jar&quot;</span><br>    <span class="hljs-attr">jdbc_driver_class</span> =&gt; <span class="hljs-string">&quot;com.mysql.jdbc.Driver&quot;</span><br>    <span class="hljs-attr">jdbc_connection_string</span> =&gt; <span class="hljs-string">&quot;jdbc:mysql://localhost:3306/memory_search&quot;</span><br>    <span class="hljs-attr">jdbc_user</span> =&gt; <span class="hljs-string">&quot;root&quot;</span><br>    <span class="hljs-attr">jdbc_password</span> =&gt; <span class="hljs-string">&quot;Dw990831&quot;</span><br>    <span class="hljs-attr">statement</span> =&gt; <span class="hljs-string">&quot;SELECT * from article where updateTime &gt; :sql_last_value and updateTime &lt; now() order by updateTime desc&quot;</span><br>    <span class="hljs-attr">use_column_value</span> =&gt; <span class="hljs-keyword">true</span><br>    <span class="hljs-attr">tracking_column_type</span> =&gt; <span class="hljs-string">&quot;timestamp&quot;</span><br>    <span class="hljs-attr">tracking_column</span> =&gt; <span class="hljs-string">&quot;updatetime&quot;</span><br>    <span class="hljs-attr">schedule</span> =&gt; <span class="hljs-string">&quot;*/5 * * * * *&quot;</span><br>    <span class="hljs-attr">jdbc_default_timezone</span> =&gt; <span class="hljs-string">&quot;Asia/Shanghai&quot;</span><br>  &#125;<br>&#125;<br><br><span class="hljs-keyword">filter</span> &#123;<br>  mutate &#123;<br>    <span class="hljs-attr">rename</span> =&gt; &#123;<br>      <span class="hljs-string">&quot;updatetime&quot;</span> =&gt; <span class="hljs-string">&quot;updateTime&quot;</span><br>      <span class="hljs-string">&quot;userid&quot;</span> =&gt; <span class="hljs-string">&quot;userId&quot;</span><br>      <span class="hljs-string">&quot;createtime&quot;</span> =&gt; <span class="hljs-string">&quot;createTime&quot;</span><br>      <span class="hljs-string">&quot;isdelete&quot;</span> =&gt; <span class="hljs-string">&quot;isDelete&quot;</span><br>    &#125;<br>    <span class="hljs-keyword">remove_field</span> =&gt; [<span class="hljs-string">&quot;thumbnum&quot;</span>, <span class="hljs-string">&quot;favournum&quot;</span>]<br>  &#125;<br>&#125;<br><br><span class="hljs-keyword">output</span> &#123;<br>  stdout &#123; <span class="hljs-attr">codec</span> =&gt; rubydebug &#125;<br>    <span class="hljs-keyword">elasticsearch</span> &#123;  <br>    <span class="hljs-attr">hosts</span> =&gt; [<span class="hljs-string">&quot;127.0.0.1:9200&quot;</span>]  <br>    <span class="hljs-attr">index</span> =&gt; <span class="hljs-string">&quot;article_v1&quot;</span>  <br>    <span class="hljs-attr">document_id</span> =&gt; <span class="hljs-string">&quot;%&#123;id&#125;&quot;</span>  <br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li>执行这条命令即可：</li>
</ul>
<figure class="highlight livescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs livescript">.<span class="hljs-string">\bin\logstash.bat</span> -f .<span class="hljs-string">\config\myTask.conf</span> -f .<span class="hljs-string">\config\myTask2.conf</span><br></code></pre></td></tr></table></figure>

<ul>
<li>有关 Logstash 的配置，还需要更多了解，目前知识掌握了 MSQL 向 ES 的映射配置<strong>（2023/11/16晚）</strong></li>
</ul>
<blockquote>
<p>SQL，多输入，多输出</p>
</blockquote>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231107213230435.png" alt="image-20231107213230435"></p>
<h2 id="Kibana-监控面板"><a href="#Kibana-监控面板" class="headerlink" title="Kibana 监控面板"></a>Kibana 监控面板</h2><ul>
<li><p>其实没什么好讲的，不过还是稍微体验了一下：<strong>（2023/12/03午）</strong></p>
</li>
<li><p>简单地记录一下吧：</p>
</li>
<li><h5 id="找到监控看板："><a href="#找到监控看板：" class="headerlink" title="找到监控看板："></a>找到监控看板：</h5></li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231203121821257.png" alt="image-20231203121821257"></p>
<ul>
<li><h5 id="创建可视化看板"><a href="#创建可视化看板" class="headerlink" title="创建可视化看板"></a>创建可视化看板</h5></li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231203122616094.png" alt="image-20231203122616094"></p>
<ul>
<li><h5 id="进入看板管理页面"><a href="#进入看板管理页面" class="headerlink" title="进入看板管理页面"></a>进入看板管理页面</h5></li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231203122622671.png" alt="image-20231203122622671"></p>
<ul>
<li><h5 id="查看已创建的看板列表，创建新的看板"><a href="#查看已创建的看板列表，创建新的看板" class="headerlink" title="查看已创建的看板列表，创建新的看板"></a>查看已创建的看板列表，创建新的看板</h5></li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231203122626820.png" alt="image-20231203122626820"></p>
<ul>
<li><h5 id="创建新的看板"><a href="#创建新的看板" class="headerlink" title="创建新的看板"></a>创建新的看板</h5></li>
</ul>
<blockquote>
<p>如下图所示：</p>
<p>看板的命名很有意思，<strong>看板的命名必须要匹配到已经创建的索引名</strong>，还不能重复，也就是说：</p>
<p><strong>每个索引只可以创建一个看板</strong>，至少我目前的看法是这样的<strong>（2023/12/03午）</strong></p>
</blockquote>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231203122632293.png" alt="image-20231203122632293"></p>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231203122639112.png" alt="image-20231203122639112"></p>
<ul>
<li>创建好新的看板之后，就可以再次进入 <code>DashBorad</code> 界面了，我们创建的可视化看板可以投入使用了</li>
<li>这里<strong>简单地介绍下各个板块的作用</strong>吧，其他没有什么好讲的，有时间玩玩就可以</li>
</ul>
<p><img src="https://gitee.com/deng-2022/pictures/raw/master/images/image-20231203123414249.png" alt="image-20231203123414249"></p>
<ul>
<li>使用 <code>Kibana</code> 可视化监控看板的教程到这里就结束了<strong>（2023/12/03午）</strong></li>
</ul>
<h2 id="其他"><a href="#其他" class="headerlink" title="其他"></a>其他</h2><h3 id="搜索建议"><a href="#搜索建议" class="headerlink" title="搜索建议"></a>搜索建议</h3><ul>
<li><h5 id="官方文档：-Suggesters-Elasticsearch-Guide-7-17-Elastic（2023-09-25晚）"><a href="#官方文档：-Suggesters-Elasticsearch-Guide-7-17-Elastic（2023-09-25晚）" class="headerlink" title="官方文档：[Suggesters | Elasticsearch Guide 7.17] | Elastic（2023/09/25晚）"></a>官方文档：[Suggesters | Elasticsearch Guide <a target="_blank" rel="noopener" href="https://www.elastic.co/guide/en/elasticsearch/reference/7.17/search-suggesters.html">7.17] | Elastic</a>（2023/09/25晚）</h5></li>
</ul>
<figure class="highlight ada"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs ada">POST my-index-<span class="hljs-number">000001</span>/_search<br>&#123;<br>  <span class="hljs-string">&quot;query&quot;</span> : &#123;<br>    <span class="hljs-string">&quot;match&quot;</span>: &#123;<br>      <span class="hljs-string">&quot;message&quot;</span>: <span class="hljs-string">&quot;tring out Elasticsearch&quot;</span><br>    &#125;<br>  &#125;,<br>  <span class="hljs-string">&quot;suggest&quot;</span> : &#123;<br>    <span class="hljs-string">&quot;my-suggestion&quot;</span> : &#123;<br>      <span class="hljs-string">&quot;text&quot;</span> : &quot;<span class="hljs-type">tring</span> <span class="hljs-keyword">out</span> Elasticsearch<span class="hljs-string">&quot;,</span><br><span class="hljs-string">      &quot;</span>term<span class="hljs-string">&quot; : &#123;</span><br><span class="hljs-string">        &quot;</span>field<span class="hljs-string">&quot; : &quot;</span>message<span class="hljs-string">&quot;</span><br><span class="hljs-string">      &#125;</span><br><span class="hljs-string">    &#125;</span><br><span class="hljs-string">  &#125;</span><br><span class="hljs-string">&#125;</span><br></code></pre></td></tr></table></figure>

<h3 id="搜索高亮"><a href="#搜索高亮" class="headerlink" title="搜索高亮"></a>搜索高亮</h3><ul>
<li><h5 id="官方文档：-Highlighting-Elasticsearch-Guide-7-17-Elastic"><a href="#官方文档：-Highlighting-Elasticsearch-Guide-7-17-Elastic" class="headerlink" title="官方文档：[Highlighting | Elasticsearch Guide 7.17] | Elastic"></a>官方文档：[Highlighting | Elasticsearch Guide <a target="_blank" rel="noopener" href="https://www.elastic.co/guide/en/elasticsearch/reference/7.17/highlighting.html">7.17] | Elastic</a></h5></li>
<li><h5 id="如何使搜索词高亮？ES文档里有现成的demo："><a href="#如何使搜索词高亮？ES文档里有现成的demo：" class="headerlink" title="如何使搜索词高亮？ES文档里有现成的demo："></a>如何使搜索词高亮？ES文档里有现成的demo：</h5></li>
</ul>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs css">GET /_search<br>&#123;<br>  &quot;query&quot;: &#123;<br>    &quot;match&quot;: &#123; &quot;<span class="hljs-attribute">content</span>&quot;: <span class="hljs-string">&quot;kimchy&quot;</span> &#125;<br>  &#125;,<br>  &quot;highlight&quot;: &#123;<br>    &quot;fields&quot;: &#123;<br>      &quot;<span class="hljs-attribute">content</span>&quot;: &#123;&#125;<br>    &#125;<br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure>

<ul>
<li>我们执行搜索，能得到如下标识出来的高亮词：</li>
</ul>
<p><img src="C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20231001205230841.png" alt="image-20231001205230841"></p>
<h4 id="后端"><a href="#后端" class="headerlink" title="后端"></a>后端</h4><ul>
<li><h5 id="我们使用-Java客户端，这样编写："><a href="#我们使用-Java客户端，这样编写：" class="headerlink" title="我们使用 Java客户端，这样编写："></a>我们使用 Java客户端，这样编写：</h5></li>
<li><h5 id="使所有字段内匹配的关键字高亮：-（2023-10-01晚）"><a href="#使所有字段内匹配的关键字高亮：-（2023-10-01晚）" class="headerlink" title="使所有字段内匹配的关键字高亮： （2023/10/01晚）"></a>使所有字段内匹配的关键字高亮： <strong>（2023/10/01晚）</strong></h5></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs java">搜索关键词高亮<br><span class="hljs-type">HighlightBuilder</span> <span class="hljs-variable">highlightBuilder</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">HighlightBuilder</span>();<br>highlightBuilder.field(<span class="hljs-string">&quot;*&quot;</span>)<br>        .preTags(<span class="hljs-string">&quot;&lt;font color=&#x27;#eea6b7&#x27;&gt;&quot;</span>)<br>        .postTags(<span class="hljs-string">&quot;&lt;/font&gt;&quot;</span>); <span class="hljs-comment">//所有的字段都高亮</span><br>highlightBuilder.requireFieldMatch(<span class="hljs-literal">false</span>);<span class="hljs-comment">//如果要多个字段高亮,这项要为false</span><br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="或者指定固定字段内的关键词高亮："><a href="#或者指定固定字段内的关键词高亮：" class="headerlink" title="或者指定固定字段内的关键词高亮："></a>或者指定固定字段内的关键词高亮：</h5></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">//查询带highlight，标题和内容都带上</span><br>      <span class="hljs-type">HighlightBuilder</span> <span class="hljs-variable">highlightBuilder</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">HighlightBuilder</span>()<br>              .field(<span class="hljs-string">&quot;content&quot;</span>)<br>              .requireFieldMatch(<span class="hljs-literal">false</span>)<br>              .preTags(<span class="hljs-string">&quot;&lt;font color=&#x27;#eea6b7&#x27;&gt;&quot;</span>)<br>              .postTags(<span class="hljs-string">&quot;&lt;/font&gt;&quot;</span>);<br>      highlightBuilder.field(<span class="hljs-string">&quot;title&quot;</span>)<br>              .requireFieldMa<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="在构造查询中，配置关键字高亮显示："><a href="#在构造查询中，配置关键字高亮显示：" class="headerlink" title="在构造查询中，配置关键字高亮显示："></a>在构造查询中，配置关键字高亮显示：</h5></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// 构造查询</span><br>     <span class="hljs-type">NativeSearchQuery</span> <span class="hljs-variable">searchQuery</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">NativeSearchQueryBuilder</span>()<br>             .withQuery(boolQueryBuilder)<br>             .withHighlightBuilder(highlightBuilder)<br>             .withPageable(pageRequest)<br>             .withSorts(sortBuilder).build();<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="我们抽象出一个类，存放获取的高亮关键词："><a href="#我们抽象出一个类，存放获取的高亮关键词：" class="headerlink" title="我们抽象出一个类，存放获取的高亮关键词："></a>我们抽象出一个类，存放获取的高亮关键词：</h5></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs java">List&lt;SearchHit&lt;PostEsDTO&gt;&gt; searchHitList = searchHits.getSearchHits();<br>         <span class="hljs-comment">// 搜索关键词高亮</span><br>         Map&lt;Long, PostEsHighlightData&gt; highlightDataMap = <span class="hljs-keyword">new</span> <span class="hljs-title class_">HashMap</span>&lt;&gt;();<br>         <span class="hljs-keyword">for</span> (SearchHit hit : searchHits.getSearchHits()) &#123;<br>             <span class="hljs-type">PostEsHighlightData</span> <span class="hljs-variable">data</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">PostEsHighlightData</span>();<br>             data.setId(Long.valueOf(hit.getId()));<br>             <span class="hljs-keyword">if</span> (hit.getHighlightFields().get(<span class="hljs-string">&quot;title&quot;</span>) != <span class="hljs-literal">null</span>) &#123;<br>                 <span class="hljs-type">String</span> <span class="hljs-variable">highlightTitle</span> <span class="hljs-operator">=</span> String.valueOf(hit.getHighlightFields().get(<span class="hljs-string">&quot;title&quot;</span>));<br>                 data.setTitle(highlightTitle.substring(<span class="hljs-number">1</span>, highlightTitle.length() - <span class="hljs-number">1</span>));<br>                 System.out.println(data.getTitle());<br>             &#125;<br>             <span class="hljs-keyword">if</span> (hit.getHighlightFields().get(<span class="hljs-string">&quot;content&quot;</span>) != <span class="hljs-literal">null</span>) &#123;<br>                 <span class="hljs-type">String</span> <span class="hljs-variable">highlightContent</span> <span class="hljs-operator">=</span> String.valueOf(hit.getHighlightFields().get(<span class="hljs-string">&quot;content&quot;</span>));<br>                 data.setContent(highlightContent.substring(<span class="hljs-number">1</span>, highlightContent.length() - <span class="hljs-number">1</span>));<br>                 System.out.println(data.getContent());<br>             &#125;<br>             highlightDataMap.put(data.getId(), data);<br>         &#125;<br></code></pre></td></tr></table></figure>

<ul>
<li><h5 id="根据-id-拿到每一个-Post对象，使用高亮关键词替换原文本，返回结果："><a href="#根据-id-拿到每一个-Post对象，使用高亮关键词替换原文本，返回结果：" class="headerlink" title="根据 id 拿到每一个 Post对象，使用高亮关键词替换原文本，返回结果："></a>根据 id 拿到每一个 Post对象，使用高亮关键词替换原文本，返回结果：</h5></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-comment">// id列表</span><br>            List&lt;Long&gt; postIdList = searchHitList.stream().map(searchHit -&gt; searchHit.getContent().getId())<br>                    .collect(Collectors.toList());<br>            <span class="hljs-comment">// 根据id查找数据集</span><br>            List&lt;Post&gt; postList = baseMapper.selectBatchIds(postIdList);<br>            <span class="hljs-keyword">if</span> (postList != <span class="hljs-literal">null</span>) &#123;<br>                Map&lt;Long, List&lt;Post&gt;&gt; idPostMap = postList.stream().collect(Collectors.groupingBy(Post::getId));<br>                postIdList.forEach(postId -&gt; &#123;<br>                    <span class="hljs-keyword">if</span> (idPostMap.containsKey(postId)) &#123;<br>                        <span class="hljs-comment">// 搜索关键词高亮替换</span><br>                        <span class="hljs-type">Post</span> <span class="hljs-variable">post</span> <span class="hljs-operator">=</span> idPostMap.get(postId).get(<span class="hljs-number">0</span>);<br>                        <span class="hljs-type">String</span> <span class="hljs-variable">hl_title</span> <span class="hljs-operator">=</span> highlightDataMap.get(postId).getTitle();<br>                        <span class="hljs-type">String</span> <span class="hljs-variable">hl_content</span> <span class="hljs-operator">=</span> highlightDataMap.get(postId).getContent();<br>                        <span class="hljs-keyword">if</span> (hl_title != <span class="hljs-literal">null</span> &amp;&amp; hl_title.trim() != <span class="hljs-string">&quot;&quot;</span>) &#123;<br>                            post.setTitle(hl_title);<br>                        &#125;<br>                        <span class="hljs-keyword">if</span> (hl_content != <span class="hljs-literal">null</span> &amp;&amp; hl_content.trim() != <span class="hljs-string">&quot;&quot;</span>) &#123;<br>                            post.setContent(hl_content);<br>                        &#125;<br>                        resourceList.add(post);<br>                    &#125; <span class="hljs-keyword">else</span> &#123;<br>                        <span class="hljs-comment">// 从 es 清空 db 已物理删除的数据</span><br>                        <span class="hljs-type">String</span> <span class="hljs-variable">delete</span> <span class="hljs-operator">=</span> elasticsearchRestTemplate.delete(String.valueOf(postId), PostEsDTO.class);<br>                        log.info(<span class="hljs-string">&quot;delete post &#123;&#125;&quot;</span>, delete);<br>                    &#125;<br>                &#125;);<br>            &#125;<br>        &#125;<br><br></code></pre></td></tr></table></figure>

<h4 id="前端"><a href="#前端" class="headerlink" title="前端"></a>前端</h4><ul>
<li>后端已经将关键词高亮特殊处理了，前端应该做什么呢？</li>
<li>将后端响应的文本信息，放入 <strong>v-html 属性</strong>中，即可<strong>解析出文本的 CSS 样式</strong>：</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;!--标题--&gt;<br>        &lt;template #title&gt;<br>          &lt;a href=&quot;https://www.antdv.com/&quot; v-html=&quot;item.title&quot;&gt;&lt;/a&gt;<br>        &lt;/template&gt;<br>        &lt;!--头像--&gt;<br>        &lt;template #avatar&gt;<br>          &lt;a-avatar src=&quot;https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png&quot;/&gt;<br>        &lt;/template&gt;<br>        &lt;template #description&gt;<br>          &lt;div v-html=&quot;item.content&quot; style=&quot;margin-bottom: 10px&quot;&gt;&lt;/div&gt;<br>        &lt;/template&gt;<br></code></pre></td></tr></table></figure>

<ul>
<li>这就是最终的的实现效果了：</li>
</ul>
<p><img src="C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20231001210038270.png" alt="image-20231001210038270"></p>
<ul>
<li>这让我想起了前两天刚实现过的<strong>前端解析 Markdown 格式文件</strong>的方法： <strong>（2023/10/01晚）</strong></li>
</ul>
<figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs ts"><span class="hljs-keyword">import</span> <span class="hljs-title class_">MarkdownIt</span> <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;markdown-it&#x27;</span>;<br><br><span class="hljs-comment">// Markdown语法</span><br><span class="hljs-keyword">const</span> parsedContent = <span class="hljs-title function_">ref</span>()<br><span class="hljs-keyword">const</span> md = <span class="hljs-keyword">new</span> <span class="hljs-title class_">MarkdownIt</span>();<br><span class="hljs-comment">// 使用Markdown语法接收文章内容</span><br>parsedContent.<span class="hljs-property">value</span> = md.<span class="hljs-title function_">render</span>(articleInfo.<span class="hljs-property">value</span>.<span class="hljs-property">content</span>);<br></code></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs vue">&lt;div v-html=&quot;parsedContent&quot;<br>      style=&quot;position: absolute; margin-left: 10px; margin-right: 10px; margin-top: 20px;&quot;&gt;<br> &lt;/div&gt;<br></code></pre></td></tr></table></figure>

<h3 id="搜索词建议"><a href="#搜索词建议" class="headerlink" title="搜索词建议"></a>搜索词建议</h3><ul>
<li></li>
</ul>
<h3 id="订阅数据库流水的同步方式-Canel"><a href="#订阅数据库流水的同步方式-Canel" class="headerlink" title="订阅数据库流水的同步方式 Canel"></a>订阅数据库流水的同步方式 Canel</h3><h4 id="下载、安装"><a href="#下载、安装" class="headerlink" title="下载、安装"></a>下载、安装</h4><h4 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h4><h4 id="项目导入Canel依赖"><a href="#项目导入Canel依赖" class="headerlink" title="项目导入Canel依赖"></a>项目导入Canel依赖</h4><h4 id="简单测试"><a href="#简单测试" class="headerlink" title="简单测试"></a>简单测试</h4><h3 id="Jmeter压力测试"><a href="#Jmeter压力测试" class="headerlink" title="Jmeter压力测试"></a>Jmeter压力测试</h3><ul>
<li><h5 id="下载安装：Apache-JMeter-Download-Apache-JMeter（2023-09-25晚）"><a href="#下载安装：Apache-JMeter-Download-Apache-JMeter（2023-09-25晚）" class="headerlink" title="下载安装：Apache JMeter - Download Apache JMeter（2023/09/25晚）"></a>下载安装：<a target="_blank" rel="noopener" href="https://jmeter.apache.org/download_jmeter.cgi">Apache JMeter - Download Apache JMeter</a>（2023/09/25晚）</h5></li>
<li><h5 id="流程记录（2023-09-25晚）"><a href="#流程记录（2023-09-25晚）" class="headerlink" title="流程记录（2023/09/25晚）"></a>流程记录（2023/09/25晚）</h5><ul>
<li><p>配置线程组</p>
</li>
<li><h5 id="HTTP信息头管理："><a href="#HTTP信息头管理：" class="headerlink" title="HTTP信息头管理："></a>HTTP信息头管理：</h5></li>
</ul>
<p><img src="C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20230925221226435.png" alt="image-20230925221226435"></p>
<ul>
<li><h5 id="HTTP请求默认值（作统一配置）："><a href="#HTTP请求默认值（作统一配置）：" class="headerlink" title="HTTP请求默认值（作统一配置）："></a>HTTP请求默认值（作统一配置）：</h5></li>
</ul>
<p><img src="C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20230925221314497.png" alt="image-20230925221314497"></p>
<ul>
<li><h5 id="HTTP请求"><a href="#HTTP请求" class="headerlink" title="HTTP请求"></a>HTTP请求</h5><ul>
<li>响应断言（对响应结果作断言）</li>
</ul>
<p><img src="C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20230925221439521.png" alt="image-20230925221439521"></p>
<ul>
<li>查看结果树（并发请求的结果）</li>
</ul>
<p><img src="C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20230925221619545.png" alt="image-20230925221619545"></p>
<ul>
<li>聚合报告</li>
</ul>
<p><img src="C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20230925221809099.png" alt="image-20230925221809099"></p>
</li>
</ul>
</li>
</ul>
<h1 id="-1"><a href="#-1" class="headerlink" title=""></a></h1><h1 id="1-初识elasticsearch"><a href="#1-初识elasticsearch" class="headerlink" title="1.初识elasticsearch"></a>1.初识elasticsearch</h1><h2 id="1-1-了解ES"><a href="#1-1-了解ES" class="headerlink" title="1.1.了解ES"></a>1.1.了解ES</h2><h3 id="1-1-1-elasticsearch的作用"><a href="#1-1-1-elasticsearch的作用" class="headerlink" title="1.1.1.elasticsearch的作用"></a>1.1.1.elasticsearch的作用</h3><p>elasticsearch是一款非常强大的开源搜索引擎，具备非常多强大功能，可以帮助我们从海量数据中快速找到需要的内容</p>
<p>例如：</p>
<ul>
<li><p>在GitHub搜索代码</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720193623245.png" alt="image-20210720193623245"></p>
</li>
<li><p>在电商网站搜索商品</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720193633483.png" alt="image-20210720193633483"></p>
</li>
<li><p>在百度搜索答案</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720193641907.png" alt="image-20210720193641907"></p>
</li>
<li><p>在打车软件搜索附近的车</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720193648044.png" alt="image-20210720193648044"></p>
</li>
</ul>
<h3 id="1-1-2-ELK技术栈"><a href="#1-1-2-ELK技术栈" class="headerlink" title="1.1.2.ELK技术栈"></a>1.1.2.ELK技术栈</h3><p>elasticsearch结合kibana、Logstash、Beats，也就是elastic stack（ELK）。被广泛应用在日志数据分析、实时监控等领域：</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720194008781.png" alt="image-20210720194008781"></p>
<p>而elasticsearch是elastic stack的核心，负责存储、搜索、分析数据。</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720194230265.png" alt="image-20210720194230265"></p>
<h3 id="1-1-3-elasticsearch和lucene"><a href="#1-1-3-elasticsearch和lucene" class="headerlink" title="1.1.3.elasticsearch和lucene"></a>1.1.3.elasticsearch和lucene</h3><p>elasticsearch底层是基于<strong>lucene</strong>来实现的。</p>
<p><strong>Lucene</strong>是一个Java语言的搜索引擎类库，是Apache公司的顶级项目，由DougCutting于1999年研发。官网地址：<a target="_blank" rel="noopener" href="https://lucene.apache.org/">https://lucene.apache.org/</a> 。</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720194547780.png" alt="image-20210720194547780"></p>
<p><strong>elasticsearch</strong>的发展历史：</p>
<ul>
<li>2004年Shay Banon基于Lucene开发了Compass</li>
<li>2010年Shay Banon 重写了Compass，取名为Elasticsearch。</li>
</ul>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720195001221.png" alt="image-20210720195001221"></p>
<h3 id="1-1-4-为什么不是其他搜索技术？"><a href="#1-1-4-为什么不是其他搜索技术？" class="headerlink" title="1.1.4.为什么不是其他搜索技术？"></a>1.1.4.为什么不是其他搜索技术？</h3><p>目前比较知名的搜索引擎技术排名：</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720195142535.png" alt="image-20210720195142535"></p>
<p>虽然在早期，Apache Solr是最主要的搜索引擎技术，但随着发展elasticsearch已经渐渐超越了Solr，独占鳌头：</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720195306484.png" alt="image-20210720195306484"></p>
<h3 id="1-1-5-总结"><a href="#1-1-5-总结" class="headerlink" title="1.1.5.总结"></a>1.1.5.总结</h3><p>什么是elasticsearch？</p>
<ul>
<li>一个开源的分布式搜索引擎，可以用来实现搜索、日志统计、分析、系统监控等功能</li>
</ul>
<p>什么是elastic stack（ELK）？</p>
<ul>
<li>是以elasticsearch为核心的技术栈，包括beats、Logstash、kibana、elasticsearch</li>
</ul>
<p>什么是Lucene？</p>
<ul>
<li>是Apache的开源搜索引擎类库，提供了搜索引擎的核心API</li>
</ul>
<h2 id="1-2-倒排索引"><a href="#1-2-倒排索引" class="headerlink" title="1.2.倒排索引"></a>1.2.倒排索引</h2><p>倒排索引的概念是基于MySQL这样的正向索引而言的。</p>
<h3 id="1-2-1-正向索引"><a href="#1-2-1-正向索引" class="headerlink" title="1.2.1.正向索引"></a>1.2.1.正向索引</h3><p>那么什么是正向索引呢？例如给下表（tb_goods）中的id创建索引：</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720195531539.png" alt="image-20210720195531539"></p>
<p>如果是根据id查询，那么直接走索引，查询速度非常快。</p>
<p>但如果是基于title做模糊查询，只能是逐行扫描数据，流程如下：</p>
<p>1）用户搜索数据，条件是title符合<code>&quot;%手机%&quot;</code></p>
<p>2）逐行获取数据，比如id为1的数据</p>
<p>3）判断数据中的title是否符合用户搜索条件</p>
<p>4）如果符合则放入结果集，不符合则丢弃。回到步骤1</p>
<p>逐行扫描，也就是全表扫描，随着数据量增加，其查询效率也会越来越低。当数据量达到数百万时，就是一场灾难。</p>
<h3 id="1-2-2-倒排索引"><a href="#1-2-2-倒排索引" class="headerlink" title="1.2.2.倒排索引"></a>1.2.2.倒排索引</h3><p>倒排索引中有两个非常重要的概念：</p>
<ul>
<li>文档（<code>Document</code>）：用来搜索的数据，其中的每一条数据就是一个文档。例如一个网页、一个商品信息</li>
<li>词条（<code>Term</code>）：对文档数据或用户搜索数据，利用某种算法分词，得到的具备含义的词语就是词条。例如：我是中国人，就可以分为：我、是、中国人、中国、国人这样的几个词条</li>
</ul>
<p><strong>创建倒排索引</strong>是对正向索引的一种特殊处理，流程如下：</p>
<ul>
<li>将每一个文档的数据利用算法分词，得到一个个词条</li>
<li>创建表，每行数据包括词条、词条所在文档id、位置等信息</li>
<li>因为词条唯一性，可以给词条创建索引，例如hash表结构索引</li>
</ul>
<p>如图：</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720200457207.png" alt="image-20210720200457207"></p>
<p>倒排索引的<strong>搜索流程</strong>如下（以搜索”华为手机”为例）：</p>
<p>1）用户输入条件<code>&quot;华为手机&quot;</code>进行搜索。</p>
<p>2）对用户输入内容<strong>分词</strong>，得到词条：<code>华为</code>、<code>手机</code>。</p>
<p>3）拿着词条在倒排索引中查找，可以得到包含词条的文档id：1、2、3。</p>
<p>4）拿着文档id到正向索引中查找具体文档。</p>
<p>如图：</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720201115192.png" alt="image-20210720201115192"></p>
<p>虽然要先查询倒排索引，再查询倒排索引，但是无论是词条、还是文档id都建立了索引，查询速度非常快！无需全表扫描。</p>
<h3 id="1-2-3-正向和倒排"><a href="#1-2-3-正向和倒排" class="headerlink" title="1.2.3.正向和倒排"></a>1.2.3.正向和倒排</h3><p>那么为什么一个叫做正向索引，一个叫做倒排索引呢？</p>
<ul>
<li><p><strong>正向索引</strong>是最传统的，根据id索引的方式。但根据词条查询时，必须先逐条获取每个文档，然后判断文档中是否包含所需要的词条，是<strong>根据文档找词条的过程</strong>。</p>
</li>
<li><p>而<strong>倒排索引</strong>则相反，是先找到用户要搜索的词条，根据词条得到保护词条的文档的id，然后根据id获取文档。是<strong>根据词条找文档的过程</strong>。</p>
</li>
</ul>
<p>是不是恰好反过来了？</p>
<p>那么两者方式的优缺点是什么呢？</p>
<p><strong>正向索引</strong>：</p>
<ul>
<li>优点：<ul>
<li>可以给多个字段创建索引</li>
<li>根据索引字段搜索、排序速度非常快</li>
</ul>
</li>
<li>缺点：<ul>
<li>根据非索引字段，或者索引字段中的部分词条查找时，只能全表扫描。</li>
</ul>
</li>
</ul>
<p><strong>倒排索引</strong>：</p>
<ul>
<li>优点：<ul>
<li>根据词条搜索、模糊搜索时，速度非常快</li>
</ul>
</li>
<li>缺点：<ul>
<li>只能给词条创建索引，而不是字段</li>
<li>无法根据字段做排序</li>
</ul>
</li>
</ul>
<h2 id="1-3-es的一些概念"><a href="#1-3-es的一些概念" class="headerlink" title="1.3.es的一些概念"></a>1.3.es的一些概念</h2><p>elasticsearch中有很多独有的概念，与mysql中略有差别，但也有相似之处。</p>
<h3 id="1-3-1-文档和字段"><a href="#1-3-1-文档和字段" class="headerlink" title="1.3.1.文档和字段"></a>1.3.1.文档和字段</h3><p>elasticsearch是面向<strong>文档（Document）</strong>存储的，可以是数据库中的一条商品数据，一个订单信息。文档数据会被序列化为json格式后存储在elasticsearch中：</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720202707797.png" alt="image-20210720202707797"></p>
<p>而Json文档中往往包含很多的<strong>字段（Field）</strong>，类似于数据库中的列。</p>
<h3 id="1-3-2-索引和映射"><a href="#1-3-2-索引和映射" class="headerlink" title="1.3.2.索引和映射"></a>1.3.2.索引和映射</h3><p><strong>索引（Index）</strong>，就是相同类型的文档的集合。</p>
<p>例如：</p>
<ul>
<li>所有用户文档，就可以组织在一起，称为用户的索引；</li>
<li>所有商品的文档，可以组织在一起，称为商品的索引；</li>
<li>所有订单的文档，可以组织在一起，称为订单的索引；</li>
</ul>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720203022172.png" alt="image-20210720203022172"></p>
<p>因此，我们可以把索引当做是数据库中的表。</p>
<p>数据库的表会有约束信息，用来定义表的结构、字段的名称、类型等信息。因此，索引库中就有<strong>映射（mapping）</strong>，是索引中文档的字段约束信息，类似表的结构约束。</p>
<h3 id="1-3-3-mysql与elasticsearch"><a href="#1-3-3-mysql与elasticsearch" class="headerlink" title="1.3.3.mysql与elasticsearch"></a>1.3.3.mysql与elasticsearch</h3><p>我们统一的把mysql与elasticsearch的概念做一下对比：</p>
<table>
<thead>
<tr>
<th><strong>MySQL</strong></th>
<th align="center"><strong>Elasticsearch</strong></th>
<th><strong>说明</strong></th>
</tr>
</thead>
<tbody><tr>
<td>Table</td>
<td align="center">Index</td>
<td>索引(index)，就是文档的集合，类似数据库的表(table)</td>
</tr>
<tr>
<td>Row</td>
<td align="center">Document</td>
<td>文档（Document），就是一条条的数据，类似数据库中的行（Row），文档都是JSON格式</td>
</tr>
<tr>
<td>Column</td>
<td align="center">Field</td>
<td>字段（Field），就是JSON文档中的字段，类似数据库中的列（Column）</td>
</tr>
<tr>
<td>Schema</td>
<td align="center">Mapping</td>
<td>Mapping（映射）是索引中文档的约束，例如字段类型约束。类似数据库的表结构（Schema）</td>
</tr>
<tr>
<td>SQL</td>
<td align="center">DSL</td>
<td>DSL是elasticsearch提供的JSON风格的请求语句，用来操作elasticsearch，实现CRUD</td>
</tr>
</tbody></table>
<p>是不是说，我们学习了elasticsearch就不再需要mysql了呢？</p>
<p>并不是如此，两者各自有自己的擅长支出：</p>
<ul>
<li><h5 id="Mysql：擅长事务类型操作，可以确保数据的安全和一致性"><a href="#Mysql：擅长事务类型操作，可以确保数据的安全和一致性" class="headerlink" title="Mysql：擅长事务类型操作，可以确保数据的安全和一致性"></a>Mysql：擅长事务类型操作，可以确保数据的安全和一致性</h5></li>
<li><h5 id="Elasticsearch：擅长海量数据的搜索、分析、计算"><a href="#Elasticsearch：擅长海量数据的搜索、分析、计算" class="headerlink" title="Elasticsearch：擅长海量数据的搜索、分析、计算"></a>Elasticsearch：擅长海量数据的搜索、分析、计算</h5></li>
</ul>
<p>因此在企业中，往往是两者结合使用：</p>
<ul>
<li>对安全性要求较高的写操作，使用mysql实现</li>
<li>对查询性能要求较高的搜索需求，使用elasticsearch实现</li>
<li>两者再基于某种方式，实现数据的同步，保证一致性</li>
</ul>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720203534945.png" alt="image-20210720203534945"></p>
<h2 id="1-4-安装es、kibana"><a href="#1-4-安装es、kibana" class="headerlink" title="1.4.安装es、kibana"></a>1.4.安装es、kibana</h2><h3 id="1-4-1-安装"><a href="#1-4-1-安装" class="headerlink" title="1.4.1.安装"></a>1.4.1.安装</h3><p>参考课前资料：</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720203805350.png" alt="image-20210720203805350"> </p>
<h3 id="1-4-2-分词器"><a href="#1-4-2-分词器" class="headerlink" title="1.4.2.分词器"></a>1.4.2.分词器</h3><p>参考课前资料：</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720203805350.png" alt="image-20210720203805350"> </p>
<h3 id="1-4-3-总结"><a href="#1-4-3-总结" class="headerlink" title="1.4.3.总结"></a>1.4.3.总结</h3><p>分词器的作用是什么？</p>
<ul>
<li>创建倒排索引时对文档分词</li>
<li>用户搜索时，对输入的内容分词</li>
</ul>
<p>IK分词器有几种模式？</p>
<ul>
<li>ik_smart：智能切分，粗粒度</li>
<li>ik_max_word：最细切分，细粒度</li>
</ul>
<p>IK分词器如何拓展词条？如何停用词条？</p>
<ul>
<li>利用config目录的IkAnalyzer.cfg.xml文件添加拓展词典和停用词典</li>
<li>在词典中添加拓展词条或者停用词条</li>
</ul>
<h1 id="2-索引库操作"><a href="#2-索引库操作" class="headerlink" title="2.索引库操作"></a>2.索引库操作</h1><p>索引库就类似数据库表，mapping映射就类似表的结构。</p>
<p>我们要向es中存储数据，必须先创建“库”和“表”。</p>
<h2 id="2-1-mapping映射属性"><a href="#2-1-mapping映射属性" class="headerlink" title="2.1.mapping映射属性"></a>2.1.mapping映射属性</h2><p>mapping是对索引库中文档的约束，常见的mapping属性包括：</p>
<ul>
<li>type：字段数据类型，常见的简单类型有：<ul>
<li>字符串：text（可分词的文本）、keyword（精确值，例如：品牌、国家、ip地址）</li>
<li>数值：long、integer、short、byte、double、float、</li>
<li>布尔：boolean</li>
<li>日期：date</li>
<li>对象：object</li>
</ul>
</li>
<li>index：是否创建索引，默认为true</li>
<li>analyzer：使用哪种分词器</li>
<li>properties：该字段的子字段</li>
</ul>
<p>例如下面的json文档：</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs json"><span class="hljs-punctuation">&#123;</span><br>    <span class="hljs-attr">&quot;age&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-number">21</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-attr">&quot;weight&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-number">52.1</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-attr">&quot;isMarried&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><span class="hljs-punctuation">,</span><br>    <span class="hljs-attr">&quot;info&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;黑马程序员Java讲师&quot;</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-attr">&quot;email&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;zy@itcast.cn&quot;</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-attr">&quot;score&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-number">99.1</span><span class="hljs-punctuation">,</span> <span class="hljs-number">99.5</span><span class="hljs-punctuation">,</span> <span class="hljs-number">98.9</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-attr">&quot;name&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">&#123;</span><br>        <span class="hljs-attr">&quot;firstName&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;云&quot;</span><span class="hljs-punctuation">,</span><br>        <span class="hljs-attr">&quot;lastName&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;赵&quot;</span><br>    <span class="hljs-punctuation">&#125;</span><br><span class="hljs-punctuation">&#125;</span><br></code></pre></td></tr></table></figure>

<p>对应的每个字段映射（mapping）：</p>
<ul>
<li>age：类型为 integer；参与搜索，因此需要index为true；无需分词器</li>
<li>weight：类型为float；参与搜索，因此需要index为true；无需分词器</li>
<li>isMarried：类型为boolean；参与搜索，因此需要index为true；无需分词器</li>
<li>info：类型为字符串，需要分词，因此是text；参与搜索，因此需要index为true；分词器可以用ik_smart</li>
<li>email：类型为字符串，但是不需要分词，因此是keyword；不参与搜索，因此需要index为false；无需分词器</li>
<li>score：虽然是数组，但是我们只看元素的类型，类型为float；参与搜索，因此需要index为true；无需分词器</li>
<li>name：类型为object，需要定义多个子属性<ul>
<li>name.firstName；类型为字符串，但是不需要分词，因此是keyword；参与搜索，因此需要index为true；无需分词器</li>
<li>name.lastName；类型为字符串，但是不需要分词，因此是keyword；参与搜索，因此需要index为true；无需分词器</li>
</ul>
</li>
</ul>
<h2 id="2-2-索引库的CRUD"><a href="#2-2-索引库的CRUD" class="headerlink" title="2.2.索引库的CRUD"></a>2.2.索引库的CRUD</h2><p>这里我们统一使用Kibana编写DSL的方式来演示。</p>
<h3 id="2-2-1-创建索引库和映射"><a href="#2-2-1-创建索引库和映射" class="headerlink" title="2.2.1.创建索引库和映射"></a>2.2.1.创建索引库和映射</h3><h4 id="基本语法："><a href="#基本语法：" class="headerlink" title="基本语法："></a>基本语法：</h4><ul>
<li>请求方式：PUT</li>
<li>请求路径：/索引库名，可以自定义</li>
<li>请求参数：mapping映射</li>
</ul>
<p>格式：</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs json">PUT /索引库名称<br><span class="hljs-punctuation">&#123;</span><br>  <span class="hljs-attr">&quot;mappings&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">&#123;</span><br>    <span class="hljs-attr">&quot;properties&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">&#123;</span><br>      <span class="hljs-attr">&quot;字段名&quot;</span><span class="hljs-punctuation">:</span><span class="hljs-punctuation">&#123;</span><br>        <span class="hljs-attr">&quot;type&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;text&quot;</span><span class="hljs-punctuation">,</span><br>        <span class="hljs-attr">&quot;analyzer&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;ik_smart&quot;</span><br>      <span class="hljs-punctuation">&#125;</span><span class="hljs-punctuation">,</span><br>      <span class="hljs-attr">&quot;字段名2&quot;</span><span class="hljs-punctuation">:</span><span class="hljs-punctuation">&#123;</span><br>        <span class="hljs-attr">&quot;type&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;keyword&quot;</span><span class="hljs-punctuation">,</span><br>        <span class="hljs-attr">&quot;index&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;false&quot;</span><br>      <span class="hljs-punctuation">&#125;</span><span class="hljs-punctuation">,</span><br>      <span class="hljs-attr">&quot;字段名3&quot;</span><span class="hljs-punctuation">:</span><span class="hljs-punctuation">&#123;</span><br>        <span class="hljs-attr">&quot;properties&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">&#123;</span><br>          <span class="hljs-attr">&quot;子字段&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">&#123;</span><br>            <span class="hljs-attr">&quot;type&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;keyword&quot;</span><br>          <span class="hljs-punctuation">&#125;</span><br>        <span class="hljs-punctuation">&#125;</span><br>      <span class="hljs-punctuation">&#125;</span><span class="hljs-punctuation">,</span><br>      <span class="hljs-comment">// ...略</span><br>    <span class="hljs-punctuation">&#125;</span><br>  <span class="hljs-punctuation">&#125;</span><br><span class="hljs-punctuation">&#125;</span><br></code></pre></td></tr></table></figure>



<h4 id="示例："><a href="#示例：" class="headerlink" title="示例："></a>示例：</h4><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs sh">PUT /heima<br>&#123;<br>  <span class="hljs-string">&quot;mappings&quot;</span>: &#123;<br>    <span class="hljs-string">&quot;properties&quot;</span>: &#123;<br>      <span class="hljs-string">&quot;info&quot;</span>:&#123;<br>        <span class="hljs-string">&quot;type&quot;</span>: <span class="hljs-string">&quot;text&quot;</span>,<br>        <span class="hljs-string">&quot;analyzer&quot;</span>: <span class="hljs-string">&quot;ik_smart&quot;</span><br>      &#125;,<br>      <span class="hljs-string">&quot;email&quot;</span>:&#123;<br>        <span class="hljs-string">&quot;type&quot;</span>: <span class="hljs-string">&quot;keyword&quot;</span>,<br>        <span class="hljs-string">&quot;index&quot;</span>: <span class="hljs-string">&quot;falsae&quot;</span><br>      &#125;,<br>      <span class="hljs-string">&quot;name&quot;</span>:&#123;<br>        <span class="hljs-string">&quot;properties&quot;</span>: &#123;<br>          <span class="hljs-string">&quot;firstName&quot;</span>: &#123;<br>            <span class="hljs-string">&quot;type&quot;</span>: <span class="hljs-string">&quot;keyword&quot;</span><br>          &#125;<br>        &#125;<br>      &#125;,<br>      // ... 略<br>    &#125;<br>  &#125;<br>&#125;<br></code></pre></td></tr></table></figure>



<h3 id="2-2-2-查询索引库"><a href="#2-2-2-查询索引库" class="headerlink" title="2.2.2.查询索引库"></a>2.2.2.查询索引库</h3><p><strong>基本语法</strong>：</p>
<ul>
<li><p>请求方式：GET</p>
</li>
<li><p>请求路径：/索引库名</p>
</li>
<li><p>请求参数：无</p>
</li>
</ul>
<p><strong>格式</strong>：</p>
<figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs routeros"><span class="hljs-built_in">GET</span> /索引库名<br></code></pre></td></tr></table></figure>



<p><strong>示例</strong>：</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720211019329.png" alt="image-20210720211019329"></p>
<h3 id="2-2-3-修改索引库"><a href="#2-2-3-修改索引库" class="headerlink" title="2.2.3.修改索引库"></a>2.2.3.修改索引库</h3><p>倒排索引结构虽然不复杂，但是一旦数据结构改变（比如改变了分词器），就需要重新创建倒排索引，这简直是灾难。因此索引库<strong>一旦创建，无法修改mapping</strong>。</p>
<p>虽然无法修改mapping中已有的字段，但是却允许添加新的字段到mapping中，因为不会对倒排索引产生影响。</p>
<p><strong>语法说明</strong>：</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs json">PUT /索引库名/_mapping<br><span class="hljs-punctuation">&#123;</span><br>  <span class="hljs-attr">&quot;properties&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">&#123;</span><br>    <span class="hljs-attr">&quot;新字段名&quot;</span><span class="hljs-punctuation">:</span><span class="hljs-punctuation">&#123;</span><br>      <span class="hljs-attr">&quot;type&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;integer&quot;</span><br>    <span class="hljs-punctuation">&#125;</span><br>  <span class="hljs-punctuation">&#125;</span><br><span class="hljs-punctuation">&#125;</span><br></code></pre></td></tr></table></figure>



<p><strong>示例</strong>：</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720212357390.png" alt="image-20210720212357390"></p>
<h3 id="2-2-4-删除索引库"><a href="#2-2-4-删除索引库" class="headerlink" title="2.2.4.删除索引库"></a>2.2.4.删除索引库</h3><p><strong>语法：</strong></p>
<ul>
<li><p>请求方式：DELETE</p>
</li>
<li><p>请求路径：/索引库名</p>
</li>
<li><p>请求参数：无</p>
</li>
</ul>
<p><strong>格式：</strong></p>
<figure class="highlight gauss"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs gauss"><span class="hljs-keyword">DELETE</span> /索引库名<br></code></pre></td></tr></table></figure>

<p>在kibana中测试：</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720212123420.png" alt="image-20210720212123420"></p>
<h3 id="2-2-5-总结"><a href="#2-2-5-总结" class="headerlink" title="2.2.5.总结"></a>2.2.5.总结</h3><p>索引库操作有哪些？</p>
<ul>
<li>创建索引库：PUT /索引库名</li>
<li>查询索引库：GET /索引库名</li>
<li>删除索引库：DELETE /索引库名</li>
<li>添加字段：PUT /索引库名/_mapping</li>
</ul>
<h1 id="3-文档操作"><a href="#3-文档操作" class="headerlink" title="3.文档操作"></a>3.文档操作</h1><h2 id="3-1-新增文档"><a href="#3-1-新增文档" class="headerlink" title="3.1.新增文档"></a>3.1.新增文档</h2><p><strong>语法：</strong></p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs json">POST /索引库名/_doc/文档id<br><span class="hljs-punctuation">&#123;</span><br>    <span class="hljs-attr">&quot;字段1&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;值1&quot;</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-attr">&quot;字段2&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;值2&quot;</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-attr">&quot;字段3&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">&#123;</span><br>        <span class="hljs-attr">&quot;子属性1&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;值3&quot;</span><span class="hljs-punctuation">,</span><br>        <span class="hljs-attr">&quot;子属性2&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;值4&quot;</span><br>    <span class="hljs-punctuation">&#125;</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-comment">// ...</span><br><span class="hljs-punctuation">&#125;</span><br></code></pre></td></tr></table></figure>

<p><strong>示例：</strong></p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs json">POST /heima/_doc/<span class="hljs-number">1</span><br><span class="hljs-punctuation">&#123;</span><br>    <span class="hljs-attr">&quot;info&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;黑马程序员Java讲师&quot;</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-attr">&quot;email&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;zy@itcast.cn&quot;</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-attr">&quot;name&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">&#123;</span><br>        <span class="hljs-attr">&quot;firstName&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;云&quot;</span><span class="hljs-punctuation">,</span><br>        <span class="hljs-attr">&quot;lastName&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;赵&quot;</span><br>    <span class="hljs-punctuation">&#125;</span><br><span class="hljs-punctuation">&#125;</span><br></code></pre></td></tr></table></figure>

<p><strong>响应：</strong></p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720212933362.png" alt="image-20210720212933362"></p>
<h2 id="3-2-查询文档"><a href="#3-2-查询文档" class="headerlink" title="3.2.查询文档"></a>3.2.查询文档</h2><p>根据rest风格，新增是post，查询应该是get，不过查询一般都需要条件，这里我们把文档id带上。</p>
<p><strong>语法：</strong></p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs json">GET /<span class="hljs-punctuation">&#123;</span>索引库名称<span class="hljs-punctuation">&#125;</span>/_doc/<span class="hljs-punctuation">&#123;</span>id<span class="hljs-punctuation">&#125;</span><br></code></pre></td></tr></table></figure>

<p><strong>通过kibana查看数据：</strong></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-variable constant_">GET</span> /heima/_doc/<span class="hljs-number">1</span><br></code></pre></td></tr></table></figure>

<p><strong>查看结果：</strong></p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720213345003.png" alt="image-20210720213345003"></p>
<h2 id="3-3-删除文档"><a href="#3-3-删除文档" class="headerlink" title="3.3.删除文档"></a>3.3.删除文档</h2><p>删除使用DELETE请求，同样，需要根据id进行删除：</p>
<p><strong>语法：</strong></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs js"><span class="hljs-variable constant_">DELETE</span> /&#123;索引库名&#125;/_doc/id值<br></code></pre></td></tr></table></figure>

<p><strong>示例：</strong></p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs json"># 根据id删除数据<br>DELETE /heima/_doc/<span class="hljs-number">1</span><br></code></pre></td></tr></table></figure>

<p><strong>结果：</strong></p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720213634918.png" alt="image-20210720213634918"></p>
<h2 id="3-4-修改文档"><a href="#3-4-修改文档" class="headerlink" title="3.4.修改文档"></a>3.4.修改文档</h2><p>修改有两种方式：</p>
<ul>
<li>全量修改：直接覆盖原来的文档</li>
<li>增量修改：修改文档中的部分字段</li>
</ul>
<h3 id="3-4-1-全量修改"><a href="#3-4-1-全量修改" class="headerlink" title="3.4.1.全量修改"></a>3.4.1.全量修改</h3><p>全量修改是覆盖原来的文档，其本质是：</p>
<ul>
<li>根据指定的id删除文档</li>
<li>新增一个相同id的文档</li>
</ul>
<p><strong>注意</strong>：如果根据id删除时，id不存在，第二步的新增也会执行，也就从修改变成了新增操作了。</p>
<p><strong>语法：</strong></p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs json">PUT /<span class="hljs-punctuation">&#123;</span>索引库名<span class="hljs-punctuation">&#125;</span>/_doc/文档id<br><span class="hljs-punctuation">&#123;</span><br>    <span class="hljs-attr">&quot;字段1&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;值1&quot;</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-attr">&quot;字段2&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;值2&quot;</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-comment">// ... 略</span><br><span class="hljs-punctuation">&#125;</span><br><br></code></pre></td></tr></table></figure>



<p><strong>示例：</strong></p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs json">PUT /heima/_doc/<span class="hljs-number">1</span><br><span class="hljs-punctuation">&#123;</span><br>    <span class="hljs-attr">&quot;info&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;黑马程序员高级Java讲师&quot;</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-attr">&quot;email&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;zy@itcast.cn&quot;</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-attr">&quot;name&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">&#123;</span><br>        <span class="hljs-attr">&quot;firstName&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;云&quot;</span><span class="hljs-punctuation">,</span><br>        <span class="hljs-attr">&quot;lastName&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;赵&quot;</span><br>    <span class="hljs-punctuation">&#125;</span><br><span class="hljs-punctuation">&#125;</span><br></code></pre></td></tr></table></figure>



<h3 id="3-4-2-增量修改"><a href="#3-4-2-增量修改" class="headerlink" title="3.4.2.增量修改"></a>3.4.2.增量修改</h3><p>增量修改是只修改指定id匹配的文档中的部分字段。</p>
<p><strong>语法：</strong></p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs json">POST /<span class="hljs-punctuation">&#123;</span>索引库名<span class="hljs-punctuation">&#125;</span>/_update/文档id<br><span class="hljs-punctuation">&#123;</span><br>    <span class="hljs-attr">&quot;doc&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">&#123;</span><br>         <span class="hljs-attr">&quot;字段名&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;新的值&quot;</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-punctuation">&#125;</span><br><span class="hljs-punctuation">&#125;</span><br></code></pre></td></tr></table></figure>



<p><strong>示例：</strong></p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs json">POST /heima/_update/<span class="hljs-number">1</span><br><span class="hljs-punctuation">&#123;</span><br>  <span class="hljs-attr">&quot;doc&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">&#123;</span><br>    <span class="hljs-attr">&quot;email&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;ZhaoYun@itcast.cn&quot;</span><br>  <span class="hljs-punctuation">&#125;</span><br><span class="hljs-punctuation">&#125;</span><br></code></pre></td></tr></table></figure>



<h2 id="3-5-总结"><a href="#3-5-总结" class="headerlink" title="3.5.总结"></a>3.5.总结</h2><p>文档操作有哪些？</p>
<ul>
<li>创建文档：POST /{索引库名}/_doc/文档id   { json文档 }</li>
<li>查询文档：GET /{索引库名}/_doc/文档id</li>
<li>删除文档：DELETE /{索引库名}/_doc/文档id</li>
<li>修改文档：<ul>
<li>全量修改：PUT /{索引库名}/_doc/文档id { json文档 }</li>
<li>增量修改：POST /{索引库名}/_update/文档id { “doc”: {字段}}</li>
</ul>
</li>
</ul>
<h1 id="4-RestAPI"><a href="#4-RestAPI" class="headerlink" title="4.RestAPI"></a>4.RestAPI</h1><p>ES官方提供了各种不同语言的客户端，用来操作ES。这些客户端的本质就是组装DSL语句，通过http请求发送给ES。官方文档地址：<a target="_blank" rel="noopener" href="https://www.elastic.co/guide/en/elasticsearch/client/index.html">https://www.elastic.co/guide/en/elasticsearch/client/index.html</a></p>
<p>其中的Java Rest Client又包括两种：</p>
<ul>
<li>Java Low Level Rest Client</li>
<li>Java High Level Rest Client</li>
</ul>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720214555863.png" alt="image-20210720214555863"></p>
<p>我们学习的是Java HighLevel Rest Client客户端API</p>
<h2 id="4-0-导入Demo工程"><a href="#4-0-导入Demo工程" class="headerlink" title="4.0.导入Demo工程"></a>4.0.导入Demo工程</h2><h3 id="4-0-1-导入数据"><a href="#4-0-1-导入数据" class="headerlink" title="4.0.1.导入数据"></a>4.0.1.导入数据</h3><p>首先导入课前资料提供的数据库数据：</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720220400297.png" alt="image-20210720220400297"> </p>
<p>数据结构如下：</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> `tb_hotel` (<br>  `id` <span class="hljs-type">bigint</span>(<span class="hljs-number">20</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> COMMENT <span class="hljs-string">&#x27;酒店id&#x27;</span>,<br>  `name` <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> COMMENT <span class="hljs-string">&#x27;酒店名称；例：7天酒店&#x27;</span>,<br>  `address` <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> COMMENT <span class="hljs-string">&#x27;酒店地址；例：航头路&#x27;</span>,<br>  `price` <span class="hljs-type">int</span>(<span class="hljs-number">10</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> COMMENT <span class="hljs-string">&#x27;酒店价格；例：329&#x27;</span>,<br>  `score` <span class="hljs-type">int</span>(<span class="hljs-number">2</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> COMMENT <span class="hljs-string">&#x27;酒店评分；例：45，就是4.5分&#x27;</span>,<br>  `brand` <span class="hljs-type">varchar</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> COMMENT <span class="hljs-string">&#x27;酒店品牌；例：如家&#x27;</span>,<br>  `city` <span class="hljs-type">varchar</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> COMMENT <span class="hljs-string">&#x27;所在城市；例：上海&#x27;</span>,<br>  `star_name` <span class="hljs-type">varchar</span>(<span class="hljs-number">16</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">NULL</span> COMMENT <span class="hljs-string">&#x27;酒店星级，从低到高分别是：1星到5星，1钻到5钻&#x27;</span>,<br>  `business` <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">NULL</span> COMMENT <span class="hljs-string">&#x27;商圈；例：虹桥&#x27;</span>,<br>  `latitude` <span class="hljs-type">varchar</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> COMMENT <span class="hljs-string">&#x27;纬度；例：31.2497&#x27;</span>,<br>  `longitude` <span class="hljs-type">varchar</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> COMMENT <span class="hljs-string">&#x27;经度；例：120.3925&#x27;</span>,<br>  `pic` <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">NULL</span> COMMENT <span class="hljs-string">&#x27;酒店图片；例:/img/1.jpg&#x27;</span>,<br>  <span class="hljs-keyword">PRIMARY</span> KEY (`id`)<br>) ENGINE<span class="hljs-operator">=</span>InnoDB <span class="hljs-keyword">DEFAULT</span> CHARSET<span class="hljs-operator">=</span>utf8mb4;<br></code></pre></td></tr></table></figure>



<h3 id="4-0-2-导入项目"><a href="#4-0-2-导入项目" class="headerlink" title="4.0.2.导入项目"></a>4.0.2.导入项目</h3><p>然后导入课前资料提供的项目:</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720220503411.png" alt="image-20210720220503411"> </p>
<p>项目结构如图：</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720220647541.png" alt="image-20210720220647541"></p>
<h3 id="4-0-3-mapping映射分析"><a href="#4-0-3-mapping映射分析" class="headerlink" title="4.0.3.mapping映射分析"></a>4.0.3.mapping映射分析</h3><p>创建索引库，最关键的是mapping映射，而mapping映射要考虑的信息包括：</p>
<ul>
<li>字段名</li>
<li>字段数据类型</li>
<li>是否参与搜索</li>
<li>是否需要分词</li>
<li>如果分词，分词器是什么？</li>
</ul>
<p>其中：</p>
<ul>
<li>字段名、字段数据类型，可以参考数据表结构的名称和类型</li>
<li>是否参与搜索要分析业务来判断，例如图片地址，就无需参与搜索</li>
<li>是否分词呢要看内容，内容如果是一个整体就无需分词，反之则要分词</li>
<li>分词器，我们可以统一使用ik_max_word</li>
</ul>
<p>来看下酒店数据的索引库结构:</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><code class="hljs json">PUT /hotel<br><span class="hljs-punctuation">&#123;</span><br>  <span class="hljs-attr">&quot;mappings&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">&#123;</span><br>    <span class="hljs-attr">&quot;properties&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">&#123;</span><br>      <span class="hljs-attr">&quot;id&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">&#123;</span><br>        <span class="hljs-attr">&quot;type&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;keyword&quot;</span><br>      <span class="hljs-punctuation">&#125;</span><span class="hljs-punctuation">,</span><br>      <span class="hljs-attr">&quot;name&quot;</span><span class="hljs-punctuation">:</span><span class="hljs-punctuation">&#123;</span><br>        <span class="hljs-attr">&quot;type&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;text&quot;</span><span class="hljs-punctuation">,</span><br>        <span class="hljs-attr">&quot;analyzer&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;ik_max_word&quot;</span><span class="hljs-punctuation">,</span><br>        <span class="hljs-attr">&quot;copy_to&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;all&quot;</span><br>      <span class="hljs-punctuation">&#125;</span><span class="hljs-punctuation">,</span><br>      <span class="hljs-attr">&quot;address&quot;</span><span class="hljs-punctuation">:</span><span class="hljs-punctuation">&#123;</span><br>        <span class="hljs-attr">&quot;type&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;keyword&quot;</span><span class="hljs-punctuation">,</span><br>        <span class="hljs-attr">&quot;index&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><br>      <span class="hljs-punctuation">&#125;</span><span class="hljs-punctuation">,</span><br>      <span class="hljs-attr">&quot;price&quot;</span><span class="hljs-punctuation">:</span><span class="hljs-punctuation">&#123;</span><br>        <span class="hljs-attr">&quot;type&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;integer&quot;</span><br>      <span class="hljs-punctuation">&#125;</span><span class="hljs-punctuation">,</span><br>      <span class="hljs-attr">&quot;score&quot;</span><span class="hljs-punctuation">:</span><span class="hljs-punctuation">&#123;</span><br>        <span class="hljs-attr">&quot;type&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;integer&quot;</span><br>      <span class="hljs-punctuation">&#125;</span><span class="hljs-punctuation">,</span><br>      <span class="hljs-attr">&quot;brand&quot;</span><span class="hljs-punctuation">:</span><span class="hljs-punctuation">&#123;</span><br>        <span class="hljs-attr">&quot;type&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;keyword&quot;</span><span class="hljs-punctuation">,</span><br>        <span class="hljs-attr">&quot;copy_to&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;all&quot;</span><br>      <span class="hljs-punctuation">&#125;</span><span class="hljs-punctuation">,</span><br>      <span class="hljs-attr">&quot;city&quot;</span><span class="hljs-punctuation">:</span><span class="hljs-punctuation">&#123;</span><br>        <span class="hljs-attr">&quot;type&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;keyword&quot;</span><span class="hljs-punctuation">,</span><br>        <span class="hljs-attr">&quot;copy_to&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;all&quot;</span><br>      <span class="hljs-punctuation">&#125;</span><span class="hljs-punctuation">,</span><br>      <span class="hljs-attr">&quot;starName&quot;</span><span class="hljs-punctuation">:</span><span class="hljs-punctuation">&#123;</span><br>        <span class="hljs-attr">&quot;type&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;keyword&quot;</span><br>      <span class="hljs-punctuation">&#125;</span><span class="hljs-punctuation">,</span><br>      <span class="hljs-attr">&quot;business&quot;</span><span class="hljs-punctuation">:</span><span class="hljs-punctuation">&#123;</span><br>        <span class="hljs-attr">&quot;type&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;keyword&quot;</span><br>      <span class="hljs-punctuation">&#125;</span><span class="hljs-punctuation">,</span><br>      <span class="hljs-attr">&quot;location&quot;</span><span class="hljs-punctuation">:</span><span class="hljs-punctuation">&#123;</span><br>        <span class="hljs-attr">&quot;type&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;geo_point&quot;</span><br>      <span class="hljs-punctuation">&#125;</span><span class="hljs-punctuation">,</span><br>      <span class="hljs-attr">&quot;pic&quot;</span><span class="hljs-punctuation">:</span><span class="hljs-punctuation">&#123;</span><br>        <span class="hljs-attr">&quot;type&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;keyword&quot;</span><span class="hljs-punctuation">,</span><br>        <span class="hljs-attr">&quot;index&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">false</span></span><br>      <span class="hljs-punctuation">&#125;</span><span class="hljs-punctuation">,</span><br>      <span class="hljs-attr">&quot;all&quot;</span><span class="hljs-punctuation">:</span><span class="hljs-punctuation">&#123;</span><br>        <span class="hljs-attr">&quot;type&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;text&quot;</span><span class="hljs-punctuation">,</span><br>        <span class="hljs-attr">&quot;analyzer&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;ik_max_word&quot;</span><br>      <span class="hljs-punctuation">&#125;</span><br>    <span class="hljs-punctuation">&#125;</span><br>  <span class="hljs-punctuation">&#125;</span><br><span class="hljs-punctuation">&#125;</span><br></code></pre></td></tr></table></figure>



<p>几个特殊字段说明：</p>
<ul>
<li>location：地理坐标，里面包含精度、纬度</li>
<li>all：一个组合字段，其目的是将多字段的值 利用copy_to合并，提供给用户搜索</li>
</ul>
<p>地理坐标说明：</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720222110126.png" alt="image-20210720222110126"></p>
<p>copy_to说明：</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720222221516.png" alt="image-20210720222221516"></p>
<h3 id="4-0-4-初始化RestClient"><a href="#4-0-4-初始化RestClient" class="headerlink" title="4.0.4.初始化RestClient"></a>4.0.4.初始化RestClient</h3><p>在elasticsearch提供的API中，与elasticsearch一切交互都封装在一个名为RestHighLevelClient的类中，必须先完成这个对象的初始化，建立与elasticsearch的连接。</p>
<p>分为三步：</p>
<p>1）引入es的RestHighLevelClient依赖：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.elasticsearch.client<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>elasticsearch-rest-high-level-client<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span><br></code></pre></td></tr></table></figure>



<p>2）因为SpringBoot默认的ES版本是7.6.2，所以我们需要覆盖默认的ES版本：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs xml"><span class="hljs-tag">&lt;<span class="hljs-name">properties</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">java.version</span>&gt;</span>1.8<span class="hljs-tag">&lt;/<span class="hljs-name">java.version</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">elasticsearch.version</span>&gt;</span>7.12.1<span class="hljs-tag">&lt;/<span class="hljs-name">elasticsearch.version</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">properties</span>&gt;</span><br></code></pre></td></tr></table></figure>



<p>3）初始化RestHighLevelClient：</p>
<p>初始化的代码如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-type">RestHighLevelClient</span> <span class="hljs-variable">client</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">RestHighLevelClient</span>(RestClient.builder(<br>        HttpHost.create(<span class="hljs-string">&quot;http://192.168.150.101:9200&quot;</span>)<br>));<br></code></pre></td></tr></table></figure>



<p>这里为了单元测试方便，我们创建一个测试类HotelIndexTest，然后将初始化的代码编写在@BeforeEach方法中：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> cn.itcast.hotel;<br><br><span class="hljs-keyword">import</span> org.apache.http.HttpHost;<br><span class="hljs-keyword">import</span> org.elasticsearch.client.RestHighLevelClient;<br><span class="hljs-keyword">import</span> org.junit.jupiter.api.AfterEach;<br><span class="hljs-keyword">import</span> org.junit.jupiter.api.BeforeEach;<br><span class="hljs-keyword">import</span> org.junit.jupiter.api.Test;<br><br><span class="hljs-keyword">import</span> java.io.IOException;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">HotelIndexTest</span> &#123;<br>    <span class="hljs-keyword">private</span> RestHighLevelClient client;<br><br>    <span class="hljs-meta">@BeforeEach</span><br>    <span class="hljs-keyword">void</span> <span class="hljs-title function_">setUp</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-built_in">this</span>.client = <span class="hljs-keyword">new</span> <span class="hljs-title class_">RestHighLevelClient</span>(RestClient.builder(<br>                HttpHost.create(<span class="hljs-string">&quot;http://192.168.150.101:9200&quot;</span>)<br>        ));<br>    &#125;<br><br>    <span class="hljs-meta">@AfterEach</span><br>    <span class="hljs-keyword">void</span> <span class="hljs-title function_">tearDown</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> IOException &#123;<br>        <span class="hljs-built_in">this</span>.client.close();<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>





<h2 id="4-1-创建索引库"><a href="#4-1-创建索引库" class="headerlink" title="4.1.创建索引库"></a>4.1.创建索引库</h2><h3 id="4-1-1-代码解读"><a href="#4-1-1-代码解读" class="headerlink" title="4.1.1.代码解读"></a>4.1.1.代码解读</h3><p>创建索引库的API如下：</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720223049408.png" alt="image-20210720223049408"></p>
<p>代码分为三步：</p>
<ul>
<li>1）创建Request对象。因为是创建索引库的操作，因此Request是CreateIndexRequest。</li>
<li>2）添加请求参数，其实就是DSL的JSON参数部分。因为json字符串很长，这里是定义了静态字符串常量MAPPING_TEMPLATE，让代码看起来更加优雅。</li>
<li>3）发送请求，client.indices()方法的返回值是IndicesClient类型，封装了所有与索引库操作有关的方法。</li>
</ul>
<h3 id="4-1-2-完整示例"><a href="#4-1-2-完整示例" class="headerlink" title="4.1.2.完整示例"></a>4.1.2.完整示例</h3><p>在hotel-demo的cn.itcast.hotel.constants包下，创建一个类，定义mapping映射的JSON字符串常量：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> cn.itcast.hotel.constants;<br><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">HotelConstants</span> &#123;<br>    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">String</span> <span class="hljs-variable">MAPPING_TEMPLATE</span> <span class="hljs-operator">=</span> <span class="hljs-string">&quot;&#123;\n&quot;</span> +<br>            <span class="hljs-string">&quot;  \&quot;mappings\&quot;: &#123;\n&quot;</span> +<br>            <span class="hljs-string">&quot;    \&quot;properties\&quot;: &#123;\n&quot;</span> +<br>            <span class="hljs-string">&quot;      \&quot;id\&quot;: &#123;\n&quot;</span> +<br>            <span class="hljs-string">&quot;        \&quot;type\&quot;: \&quot;keyword\&quot;\n&quot;</span> +<br>            <span class="hljs-string">&quot;      &#125;,\n&quot;</span> +<br>            <span class="hljs-string">&quot;      \&quot;name\&quot;:&#123;\n&quot;</span> +<br>            <span class="hljs-string">&quot;        \&quot;type\&quot;: \&quot;text\&quot;,\n&quot;</span> +<br>            <span class="hljs-string">&quot;        \&quot;analyzer\&quot;: \&quot;ik_max_word\&quot;,\n&quot;</span> +<br>            <span class="hljs-string">&quot;        \&quot;copy_to\&quot;: \&quot;all\&quot;\n&quot;</span> +<br>            <span class="hljs-string">&quot;      &#125;,\n&quot;</span> +<br>            <span class="hljs-string">&quot;      \&quot;address\&quot;:&#123;\n&quot;</span> +<br>            <span class="hljs-string">&quot;        \&quot;type\&quot;: \&quot;keyword\&quot;,\n&quot;</span> +<br>            <span class="hljs-string">&quot;        \&quot;index\&quot;: false\n&quot;</span> +<br>            <span class="hljs-string">&quot;      &#125;,\n&quot;</span> +<br>            <span class="hljs-string">&quot;      \&quot;price\&quot;:&#123;\n&quot;</span> +<br>            <span class="hljs-string">&quot;        \&quot;type\&quot;: \&quot;integer\&quot;\n&quot;</span> +<br>            <span class="hljs-string">&quot;      &#125;,\n&quot;</span> +<br>            <span class="hljs-string">&quot;      \&quot;score\&quot;:&#123;\n&quot;</span> +<br>            <span class="hljs-string">&quot;        \&quot;type\&quot;: \&quot;integer\&quot;\n&quot;</span> +<br>            <span class="hljs-string">&quot;      &#125;,\n&quot;</span> +<br>            <span class="hljs-string">&quot;      \&quot;brand\&quot;:&#123;\n&quot;</span> +<br>            <span class="hljs-string">&quot;        \&quot;type\&quot;: \&quot;keyword\&quot;,\n&quot;</span> +<br>            <span class="hljs-string">&quot;        \&quot;copy_to\&quot;: \&quot;all\&quot;\n&quot;</span> +<br>            <span class="hljs-string">&quot;      &#125;,\n&quot;</span> +<br>            <span class="hljs-string">&quot;      \&quot;city\&quot;:&#123;\n&quot;</span> +<br>            <span class="hljs-string">&quot;        \&quot;type\&quot;: \&quot;keyword\&quot;,\n&quot;</span> +<br>            <span class="hljs-string">&quot;        \&quot;copy_to\&quot;: \&quot;all\&quot;\n&quot;</span> +<br>            <span class="hljs-string">&quot;      &#125;,\n&quot;</span> +<br>            <span class="hljs-string">&quot;      \&quot;starName\&quot;:&#123;\n&quot;</span> +<br>            <span class="hljs-string">&quot;        \&quot;type\&quot;: \&quot;keyword\&quot;\n&quot;</span> +<br>            <span class="hljs-string">&quot;      &#125;,\n&quot;</span> +<br>            <span class="hljs-string">&quot;      \&quot;business\&quot;:&#123;\n&quot;</span> +<br>            <span class="hljs-string">&quot;        \&quot;type\&quot;: \&quot;keyword\&quot;\n&quot;</span> +<br>            <span class="hljs-string">&quot;      &#125;,\n&quot;</span> +<br>            <span class="hljs-string">&quot;      \&quot;location\&quot;:&#123;\n&quot;</span> +<br>            <span class="hljs-string">&quot;        \&quot;type\&quot;: \&quot;geo_point\&quot;\n&quot;</span> +<br>            <span class="hljs-string">&quot;      &#125;,\n&quot;</span> +<br>            <span class="hljs-string">&quot;      \&quot;pic\&quot;:&#123;\n&quot;</span> +<br>            <span class="hljs-string">&quot;        \&quot;type\&quot;: \&quot;keyword\&quot;,\n&quot;</span> +<br>            <span class="hljs-string">&quot;        \&quot;index\&quot;: false\n&quot;</span> +<br>            <span class="hljs-string">&quot;      &#125;,\n&quot;</span> +<br>            <span class="hljs-string">&quot;      \&quot;all\&quot;:&#123;\n&quot;</span> +<br>            <span class="hljs-string">&quot;        \&quot;type\&quot;: \&quot;text\&quot;,\n&quot;</span> +<br>            <span class="hljs-string">&quot;        \&quot;analyzer\&quot;: \&quot;ik_max_word\&quot;\n&quot;</span> +<br>            <span class="hljs-string">&quot;      &#125;\n&quot;</span> +<br>            <span class="hljs-string">&quot;    &#125;\n&quot;</span> +<br>            <span class="hljs-string">&quot;  &#125;\n&quot;</span> +<br>            <span class="hljs-string">&quot;&#125;&quot;</span>;<br>&#125;<br></code></pre></td></tr></table></figure>



<p>在hotel-demo中的HotelIndexTest测试类中，编写单元测试，实现创建索引：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Test</span><br><span class="hljs-keyword">void</span> <span class="hljs-title function_">createHotelIndex</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> IOException &#123;<br>    <span class="hljs-comment">// 1.创建Request对象</span><br>    <span class="hljs-type">CreateIndexRequest</span> <span class="hljs-variable">request</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">CreateIndexRequest</span>(<span class="hljs-string">&quot;hotel&quot;</span>);<br>    <span class="hljs-comment">// 2.准备请求的参数：DSL语句</span><br>    request.source(MAPPING_TEMPLATE, XContentType.JSON);<br>    <span class="hljs-comment">// 3.发送请求</span><br>    client.indices().create(request, RequestOptions.DEFAULT);<br>&#125;<br></code></pre></td></tr></table></figure>



<h2 id="4-2-删除索引库"><a href="#4-2-删除索引库" class="headerlink" title="4.2.删除索引库"></a>4.2.删除索引库</h2><p>删除索引库的DSL语句非常简单：</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs json">DELETE /hotel<br></code></pre></td></tr></table></figure>

<p>与创建索引库相比：</p>
<ul>
<li>请求方式从PUT变为DELTE</li>
<li>请求路径不变</li>
<li>无请求参数</li>
</ul>
<p>所以代码的差异，注意体现在Request对象上。依然是三步走：</p>
<ul>
<li>1）创建Request对象。这次是DeleteIndexRequest对象</li>
<li>2）准备参数。这里是无参</li>
<li>3）发送请求。改用delete方法</li>
</ul>
<p>在hotel-demo中的HotelIndexTest测试类中，编写单元测试，实现删除索引：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Test</span><br><span class="hljs-keyword">void</span> <span class="hljs-title function_">testDeleteHotelIndex</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> IOException &#123;<br>    <span class="hljs-comment">// 1.创建Request对象</span><br>    <span class="hljs-type">DeleteIndexRequest</span> <span class="hljs-variable">request</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">DeleteIndexRequest</span>(<span class="hljs-string">&quot;hotel&quot;</span>);<br>    <span class="hljs-comment">// 2.发送请求</span><br>    client.indices().delete(request, RequestOptions.DEFAULT);<br>&#125;<br></code></pre></td></tr></table></figure>



<h2 id="4-3-判断索引库是否存在"><a href="#4-3-判断索引库是否存在" class="headerlink" title="4.3.判断索引库是否存在"></a>4.3.判断索引库是否存在</h2><p>判断索引库是否存在，本质就是查询，对应的DSL是：</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs json">GET /hotel<br></code></pre></td></tr></table></figure>



<p>因此与删除的Java代码流程是类似的。依然是三步走：</p>
<ul>
<li>1）创建Request对象。这次是GetIndexRequest对象</li>
<li>2）准备参数。这里是无参</li>
<li>3）发送请求。改用exists方法</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Test</span><br><span class="hljs-keyword">void</span> <span class="hljs-title function_">testExistsHotelIndex</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> IOException &#123;<br>    <span class="hljs-comment">// 1.创建Request对象</span><br>    <span class="hljs-type">GetIndexRequest</span> <span class="hljs-variable">request</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">GetIndexRequest</span>(<span class="hljs-string">&quot;hotel&quot;</span>);<br>    <span class="hljs-comment">// 2.发送请求</span><br>    <span class="hljs-type">boolean</span> <span class="hljs-variable">exists</span> <span class="hljs-operator">=</span> client.indices().exists(request, RequestOptions.DEFAULT);<br>    <span class="hljs-comment">// 3.输出</span><br>    System.err.println(exists ? <span class="hljs-string">&quot;索引库已经存在！&quot;</span> : <span class="hljs-string">&quot;索引库不存在！&quot;</span>);<br>&#125;<br></code></pre></td></tr></table></figure>



<h2 id="4-4-总结"><a href="#4-4-总结" class="headerlink" title="4.4.总结"></a>4.4.总结</h2><p>JavaRestClient操作elasticsearch的流程基本类似。核心是client.indices()方法来获取索引库的操作对象。</p>
<p>索引库操作的基本步骤：</p>
<ul>
<li>初始化RestHighLevelClient</li>
<li>创建XxxIndexRequest。XXX是Create、Get、Delete</li>
<li>准备DSL（ Create时需要，其它是无参）</li>
<li>发送请求。调用RestHighLevelClient#indices().xxx()方法，xxx是create、exists、delete</li>
</ul>
<h1 id="5-RestClient操作文档"><a href="#5-RestClient操作文档" class="headerlink" title="5.RestClient操作文档"></a>5.RestClient操作文档</h1><p>为了与索引库操作分离，我们再次参加一个测试类，做两件事情：</p>
<ul>
<li>初始化RestHighLevelClient</li>
<li>我们的酒店数据在数据库，需要利用IHotelService去查询，所以注入这个接口</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> cn.itcast.hotel;<br><br><span class="hljs-keyword">import</span> cn.itcast.hotel.pojo.Hotel;<br><span class="hljs-keyword">import</span> cn.itcast.hotel.service.IHotelService;<br><span class="hljs-keyword">import</span> org.junit.jupiter.api.AfterEach;<br><span class="hljs-keyword">import</span> org.junit.jupiter.api.BeforeEach;<br><span class="hljs-keyword">import</span> org.junit.jupiter.api.Test;<br><span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Autowired;<br><span class="hljs-keyword">import</span> org.springframework.boot.test.context.SpringBootTest;<br><br><span class="hljs-keyword">import</span> java.io.IOException;<br><span class="hljs-keyword">import</span> java.util.List;<br><br><span class="hljs-meta">@SpringBootTest</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">HotelDocumentTest</span> &#123;<br>    <span class="hljs-meta">@Autowired</span><br>    <span class="hljs-keyword">private</span> IHotelService hotelService;<br><br>    <span class="hljs-keyword">private</span> RestHighLevelClient client;<br><br>    <span class="hljs-meta">@BeforeEach</span><br>    <span class="hljs-keyword">void</span> <span class="hljs-title function_">setUp</span><span class="hljs-params">()</span> &#123;<br>        <span class="hljs-built_in">this</span>.client = <span class="hljs-keyword">new</span> <span class="hljs-title class_">RestHighLevelClient</span>(RestClient.builder(<br>                HttpHost.create(<span class="hljs-string">&quot;http://192.168.150.101:9200&quot;</span>)<br>        ));<br>    &#125;<br><br>    <span class="hljs-meta">@AfterEach</span><br>    <span class="hljs-keyword">void</span> <span class="hljs-title function_">tearDown</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> IOException &#123;<br>        <span class="hljs-built_in">this</span>.client.close();<br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure>





<h2 id="5-1-新增文档"><a href="#5-1-新增文档" class="headerlink" title="5.1.新增文档"></a>5.1.新增文档</h2><p>我们要将数据库的酒店数据查询出来，写入elasticsearch中。</p>
<h3 id="5-1-1-索引库实体类"><a href="#5-1-1-索引库实体类" class="headerlink" title="5.1.1.索引库实体类"></a>5.1.1.索引库实体类</h3><p>数据库查询后的结果是一个Hotel类型的对象。结构如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Data</span><br><span class="hljs-meta">@TableName(&quot;tb_hotel&quot;)</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Hotel</span> &#123;<br>    <span class="hljs-meta">@TableId(type = IdType.INPUT)</span><br>    <span class="hljs-keyword">private</span> Long id;<br>    <span class="hljs-keyword">private</span> String name;<br>    <span class="hljs-keyword">private</span> String address;<br>    <span class="hljs-keyword">private</span> Integer price;<br>    <span class="hljs-keyword">private</span> Integer score;<br>    <span class="hljs-keyword">private</span> String brand;<br>    <span class="hljs-keyword">private</span> String city;<br>    <span class="hljs-keyword">private</span> String starName;<br>    <span class="hljs-keyword">private</span> String business;<br>    <span class="hljs-keyword">private</span> String longitude;<br>    <span class="hljs-keyword">private</span> String latitude;<br>    <span class="hljs-keyword">private</span> String pic;<br>&#125;<br></code></pre></td></tr></table></figure>

<p>与我们的索引库结构存在差异：</p>
<ul>
<li>longitude和latitude需要合并为location</li>
</ul>
<p>因此，我们需要定义一个新的类型，与索引库结构吻合：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">package</span> cn.itcast.hotel.pojo;<br><br><span class="hljs-keyword">import</span> lombok.Data;<br><span class="hljs-keyword">import</span> lombok.NoArgsConstructor;<br><br><span class="hljs-meta">@Data</span><br><span class="hljs-meta">@NoArgsConstructor</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">HotelDoc</span> &#123;<br>    <span class="hljs-keyword">private</span> Long id;<br>    <span class="hljs-keyword">private</span> String name;<br>    <span class="hljs-keyword">private</span> String address;<br>    <span class="hljs-keyword">private</span> Integer price;<br>    <span class="hljs-keyword">private</span> Integer score;<br>    <span class="hljs-keyword">private</span> String brand;<br>    <span class="hljs-keyword">private</span> String city;<br>    <span class="hljs-keyword">private</span> String starName;<br>    <span class="hljs-keyword">private</span> String business;<br>    <span class="hljs-keyword">private</span> String location;<br>    <span class="hljs-keyword">private</span> String pic;<br><br>    <span class="hljs-keyword">public</span> <span class="hljs-title function_">HotelDoc</span><span class="hljs-params">(Hotel hotel)</span> &#123;<br>        <span class="hljs-built_in">this</span>.id = hotel.getId();<br>        <span class="hljs-built_in">this</span>.name = hotel.getName();<br>        <span class="hljs-built_in">this</span>.address = hotel.getAddress();<br>        <span class="hljs-built_in">this</span>.price = hotel.getPrice();<br>        <span class="hljs-built_in">this</span>.score = hotel.getScore();<br>        <span class="hljs-built_in">this</span>.brand = hotel.getBrand();<br>        <span class="hljs-built_in">this</span>.city = hotel.getCity();<br>        <span class="hljs-built_in">this</span>.starName = hotel.getStarName();<br>        <span class="hljs-built_in">this</span>.business = hotel.getBusiness();<br>        <span class="hljs-built_in">this</span>.location = hotel.getLatitude() + <span class="hljs-string">&quot;, &quot;</span> + hotel.getLongitude();<br>        <span class="hljs-built_in">this</span>.pic = hotel.getPic();<br>    &#125;<br>&#125;<br><br></code></pre></td></tr></table></figure>



<h3 id="5-1-2-语法说明"><a href="#5-1-2-语法说明" class="headerlink" title="5.1.2.语法说明"></a>5.1.2.语法说明</h3><p>新增文档的DSL语句如下：</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs json">POST /<span class="hljs-punctuation">&#123;</span>索引库名<span class="hljs-punctuation">&#125;</span>/_doc/<span class="hljs-number">1</span><br><span class="hljs-punctuation">&#123;</span><br>    <span class="hljs-attr">&quot;name&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;Jack&quot;</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-attr">&quot;age&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-number">21</span><br><span class="hljs-punctuation">&#125;</span><br></code></pre></td></tr></table></figure>

<p>对应的java代码如图：</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720230027240.png" alt="image-20210720230027240"></p>
<p>可以看到与创建索引库类似，同样是三步走：</p>
<ul>
<li>1）创建Request对象</li>
<li>2）准备请求参数，也就是DSL中的JSON文档</li>
<li>3）发送请求</li>
</ul>
<p>变化的地方在于，这里直接使用client.xxx()的API，不再需要client.indices()了。</p>
<h3 id="5-1-3-完整代码"><a href="#5-1-3-完整代码" class="headerlink" title="5.1.3.完整代码"></a>5.1.3.完整代码</h3><p>我们导入酒店数据，基本流程一致，但是需要考虑几点变化：</p>
<ul>
<li>酒店数据来自于数据库，我们需要先查询出来，得到hotel对象</li>
<li>hotel对象需要转为HotelDoc对象</li>
<li>HotelDoc需要序列化为json格式</li>
</ul>
<p>因此，代码整体步骤如下：</p>
<ul>
<li>1）根据id查询酒店数据Hotel</li>
<li>2）将Hotel封装为HotelDoc</li>
<li>3）将HotelDoc序列化为JSON</li>
<li>4）创建IndexRequest，指定索引库名和id</li>
<li>5）准备请求参数，也就是JSON文档</li>
<li>6）发送请求</li>
</ul>
<p>在hotel-demo的HotelDocumentTest测试类中，编写单元测试：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Test</span><br><span class="hljs-keyword">void</span> <span class="hljs-title function_">testAddDocument</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> IOException &#123;<br>    <span class="hljs-comment">// 1.根据id查询酒店数据</span><br>    <span class="hljs-type">Hotel</span> <span class="hljs-variable">hotel</span> <span class="hljs-operator">=</span> hotelService.getById(<span class="hljs-number">61083L</span>);<br>    <span class="hljs-comment">// 2.转换为文档类型</span><br>    <span class="hljs-type">HotelDoc</span> <span class="hljs-variable">hotelDoc</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">HotelDoc</span>(hotel);<br>    <span class="hljs-comment">// 3.将HotelDoc转json</span><br>    <span class="hljs-type">String</span> <span class="hljs-variable">json</span> <span class="hljs-operator">=</span> JSON.toJSONString(hotelDoc);<br><br>    <span class="hljs-comment">// 1.准备Request对象</span><br>    <span class="hljs-type">IndexRequest</span> <span class="hljs-variable">request</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">IndexRequest</span>(<span class="hljs-string">&quot;hotel&quot;</span>).id(hotelDoc.getId().toString());<br>    <span class="hljs-comment">// 2.准备Json文档</span><br>    request.source(json, XContentType.JSON);<br>    <span class="hljs-comment">// 3.发送请求</span><br>    client.index(request, RequestOptions.DEFAULT);<br>&#125;<br></code></pre></td></tr></table></figure>





<h2 id="5-2-查询文档"><a href="#5-2-查询文档" class="headerlink" title="5.2.查询文档"></a>5.2.查询文档</h2><h3 id="5-2-1-语法说明"><a href="#5-2-1-语法说明" class="headerlink" title="5.2.1.语法说明"></a>5.2.1.语法说明</h3><p>查询的DSL语句如下：</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs json">GET /hotel/_doc/<span class="hljs-punctuation">&#123;</span>id<span class="hljs-punctuation">&#125;</span><br></code></pre></td></tr></table></figure>

<p>非常简单，因此代码大概分两步：</p>
<ul>
<li>准备Request对象</li>
<li>发送请求</li>
</ul>
<p>不过查询的目的是得到结果，解析为HotelDoc，因此难点是结果的解析。完整代码如下：</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720230811674.png" alt="image-20210720230811674"></p>
<p>可以看到，结果是一个JSON，其中文档放在一个<code>_source</code>属性中，因此解析就是拿到<code>_source</code>，反序列化为Java对象即可。</p>
<p>与之前类似，也是三步走：</p>
<ul>
<li>1）准备Request对象。这次是查询，所以是GetRequest</li>
<li>2）发送请求，得到结果。因为是查询，这里调用client.get()方法</li>
<li>3）解析结果，就是对JSON做反序列化</li>
</ul>
<h3 id="5-2-2-完整代码"><a href="#5-2-2-完整代码" class="headerlink" title="5.2.2.完整代码"></a>5.2.2.完整代码</h3><p>在hotel-demo的HotelDocumentTest测试类中，编写单元测试：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Test</span><br><span class="hljs-keyword">void</span> <span class="hljs-title function_">testGetDocumentById</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> IOException &#123;<br>    <span class="hljs-comment">// 1.准备Request</span><br>    <span class="hljs-type">GetRequest</span> <span class="hljs-variable">request</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">GetRequest</span>(<span class="hljs-string">&quot;hotel&quot;</span>, <span class="hljs-string">&quot;61082&quot;</span>);<br>    <span class="hljs-comment">// 2.发送请求，得到响应</span><br>    <span class="hljs-type">GetResponse</span> <span class="hljs-variable">response</span> <span class="hljs-operator">=</span> client.get(request, RequestOptions.DEFAULT);<br>    <span class="hljs-comment">// 3.解析响应结果</span><br>    <span class="hljs-type">String</span> <span class="hljs-variable">json</span> <span class="hljs-operator">=</span> response.getSourceAsString();<br><br>    <span class="hljs-type">HotelDoc</span> <span class="hljs-variable">hotelDoc</span> <span class="hljs-operator">=</span> JSON.parseObject(json, HotelDoc.class);<br>    System.out.println(hotelDoc);<br>&#125;<br></code></pre></td></tr></table></figure>





<h2 id="5-3-删除文档"><a href="#5-3-删除文档" class="headerlink" title="5.3.删除文档"></a>5.3.删除文档</h2><p>删除的DSL是这样的：</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs json">DELETE /hotel/_doc/<span class="hljs-punctuation">&#123;</span>id<span class="hljs-punctuation">&#125;</span><br></code></pre></td></tr></table></figure>

<p>与查询相比，仅仅是请求方式从DELETE变成GET，可以想象Java代码应该依然是三步走：</p>
<ul>
<li>1）准备Request对象，因为是删除，这次是DeleteRequest对象。要指定索引库名和id</li>
<li>2）准备参数，无参</li>
<li>3）发送请求。因为是删除，所以是client.delete()方法</li>
</ul>
<p>在hotel-demo的HotelDocumentTest测试类中，编写单元测试：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Test</span><br><span class="hljs-keyword">void</span> <span class="hljs-title function_">testDeleteDocument</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> IOException &#123;<br>    <span class="hljs-comment">// 1.准备Request</span><br>    <span class="hljs-type">DeleteRequest</span> <span class="hljs-variable">request</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">DeleteRequest</span>(<span class="hljs-string">&quot;hotel&quot;</span>, <span class="hljs-string">&quot;61083&quot;</span>);<br>    <span class="hljs-comment">// 2.发送请求</span><br>    client.delete(request, RequestOptions.DEFAULT);<br>&#125;<br></code></pre></td></tr></table></figure>







<h2 id="5-4-修改文档"><a href="#5-4-修改文档" class="headerlink" title="5.4.修改文档"></a>5.4.修改文档</h2><h3 id="5-4-1-语法说明"><a href="#5-4-1-语法说明" class="headerlink" title="5.4.1.语法说明"></a>5.4.1.语法说明</h3><p>修改我们讲过两种方式：</p>
<ul>
<li>全量修改：本质是先根据id删除，再新增</li>
<li>增量修改：修改文档中的指定字段值</li>
</ul>
<p>在RestClient的API中，全量修改与新增的API完全一致，判断依据是ID：</p>
<ul>
<li>如果新增时，ID已经存在，则修改</li>
<li>如果新增时，ID不存在，则新增</li>
</ul>
<p>这里不再赘述，我们主要关注增量修改。</p>
<p>代码示例如图：</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720231040875.png" alt="image-20210720231040875"></p>
<p>与之前类似，也是三步走：</p>
<ul>
<li>1）准备Request对象。这次是修改，所以是UpdateRequest</li>
<li>2）准备参数。也就是JSON文档，里面包含要修改的字段</li>
<li>3）更新文档。这里调用client.update()方法</li>
</ul>
<h3 id="5-4-2-完整代码"><a href="#5-4-2-完整代码" class="headerlink" title="5.4.2.完整代码"></a>5.4.2.完整代码</h3><p>在hotel-demo的HotelDocumentTest测试类中，编写单元测试：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Test</span><br><span class="hljs-keyword">void</span> <span class="hljs-title function_">testUpdateDocument</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> IOException &#123;<br>    <span class="hljs-comment">// 1.准备Request</span><br>    <span class="hljs-type">UpdateRequest</span> <span class="hljs-variable">request</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">UpdateRequest</span>(<span class="hljs-string">&quot;hotel&quot;</span>, <span class="hljs-string">&quot;61083&quot;</span>);<br>    <span class="hljs-comment">// 2.准备请求参数</span><br>    request.doc(<br>        <span class="hljs-string">&quot;price&quot;</span>, <span class="hljs-string">&quot;952&quot;</span>,<br>        <span class="hljs-string">&quot;starName&quot;</span>, <span class="hljs-string">&quot;四钻&quot;</span><br>    );<br>    <span class="hljs-comment">// 3.发送请求</span><br>    client.update(request, RequestOptions.DEFAULT);<br>&#125;<br></code></pre></td></tr></table></figure>





<h2 id="5-5-批量导入文档"><a href="#5-5-批量导入文档" class="headerlink" title="5.5.批量导入文档"></a>5.5.批量导入文档</h2><p>案例需求：利用BulkRequest批量将数据库数据导入到索引库中。</p>
<p>步骤如下：</p>
<ul>
<li><p>利用mybatis-plus查询酒店数据</p>
</li>
<li><p>将查询到的酒店数据（Hotel）转换为文档类型数据（HotelDoc）</p>
</li>
<li><p>利用JavaRestClient中的BulkRequest批处理，实现批量新增文档</p>
</li>
</ul>
<h3 id="5-5-1-语法说明"><a href="#5-5-1-语法说明" class="headerlink" title="5.5.1.语法说明"></a>5.5.1.语法说明</h3><p>批量处理BulkRequest，其本质就是将多个普通的CRUD请求组合在一起发送。</p>
<p>其中提供了一个add方法，用来添加其他请求：</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720232105943.png" alt="image-20210720232105943"></p>
<p>可以看到，能添加的请求包括：</p>
<ul>
<li>IndexRequest，也就是新增</li>
<li>UpdateRequest，也就是修改</li>
<li>DeleteRequest，也就是删除</li>
</ul>
<p>因此Bulk中添加了多个IndexRequest，就是批量新增功能了。示例：</p>
<p><img src="D:/文档/Java/SpringCloud/day05-Elasticsearch01/讲义/assets/image-20210720232431383.png" alt="image-20210720232431383"></p>
<p>其实还是三步走：</p>
<ul>
<li>1）创建Request对象。这里是BulkRequest</li>
<li>2）准备参数。批处理的参数，就是其它Request对象，这里就是多个IndexRequest</li>
<li>3）发起请求。这里是批处理，调用的方法为client.bulk()方法</li>
</ul>
<p>我们在导入酒店数据时，将上述代码改造成for循环处理即可。</p>
<h3 id="5-5-2-完整代码"><a href="#5-5-2-完整代码" class="headerlink" title="5.5.2.完整代码"></a>5.5.2.完整代码</h3><p>在hotel-demo的HotelDocumentTest测试类中，编写单元测试：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@Test</span><br><span class="hljs-keyword">void</span> <span class="hljs-title function_">testBulkRequest</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> IOException &#123;<br>    <span class="hljs-comment">// 批量查询酒店数据</span><br>    List&lt;Hotel&gt; hotels = hotelService.list();<br><br>    <span class="hljs-comment">// 1.创建Request</span><br>    <span class="hljs-type">BulkRequest</span> <span class="hljs-variable">request</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">BulkRequest</span>();<br>    <span class="hljs-comment">// 2.准备参数，添加多个新增的Request</span><br>    <span class="hljs-keyword">for</span> (Hotel hotel : hotels) &#123;<br>        <span class="hljs-comment">// 2.1.转换为文档类型HotelDoc</span><br>        <span class="hljs-type">HotelDoc</span> <span class="hljs-variable">hotelDoc</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">HotelDoc</span>(hotel);<br>        <span class="hljs-comment">// 2.2.创建新增文档的Request对象</span><br>        request.add(<span class="hljs-keyword">new</span> <span class="hljs-title class_">IndexRequest</span>(<span class="hljs-string">&quot;hotel&quot;</span>)<br>                    .id(hotelDoc.getId().toString())<br>                    .source(JSON.toJSONString(hotelDoc), XContentType.JSON));<br>    &#125;<br>    <span class="hljs-comment">// 3.发送请求</span><br>    client.bulk(request, RequestOptions.DEFAULT);<br>&#125;<br></code></pre></td></tr></table></figure>





<h2 id="5-6-小结"><a href="#5-6-小结" class="headerlink" title="5.6.小结"></a>5.6.小结</h2><p>文档操作的基本步骤：</p>
<ul>
<li>初始化RestHighLevelClient</li>
<li>创建XxxRequest。XXX是Index、Get、Update、Delete、Bulk</li>
<li>准备参数（Index、Update、Bulk时需要）</li>
<li>发送请求。调用RestHighLevelClient#.xxx()方法，xxx是index、get、update、delete、bulk</li>
<li>解析结果（Get时需要）</li>
</ul>

                
              </div>
            
            <hr/>
            <div>
              <div class="post-metas my-3">
  
    <div class="post-meta mr-3 d-flex align-items-center">
      <i class="iconfont icon-category"></i>
      

<span class="category-chains">
  
  
    
      <span class="category-chain">
        
  <a href="/deng-2022/blog_2/categories/Elasticsearch/" class="category-chain-item">Elasticsearch</a>
  
  
    <span>></span>
    
  <a href="/deng-2022/blog_2/categories/Elasticsearch/Kibana/" class="category-chain-item">Kibana</a>
  
  
    <span>></span>
    
  <a href="/deng-2022/blog_2/categories/Elasticsearch/Kibana/%E7%BB%8F%E9%AA%8C/" class="category-chain-item">经验</a>
  
  

  

  

      </span>
    
  
</span>

    </div>
  
  
    <div class="post-meta">
      <i class="iconfont icon-tags"></i>
      
        <a href="/deng-2022/blog_2/tags/%E7%BB%8F%E9%AA%8C/">#经验</a>
      
        <a href="/deng-2022/blog_2/tags/Elasticsearch/">#Elasticsearch</a>
      
        <a href="/deng-2022/blog_2/tags/Kibana/">#Kibana</a>
      
    </div>
  
</div>


              
  

  <div class="license-box my-3">
    <div class="license-title">
      <div>揭秘 Elasticsearch 的神奇能力：从数据搜索到实时分析的终极指南</div>
      <div>https://atomgit.com/deng-2022/blog_2/2023/09/19/揭秘 Elasticsearch 的神奇能力：从数据搜索到实时分析的终极指南/</div>
    </div>
    <div class="license-meta">
      
        <div class="license-meta-item">
          <div>作者</div>
          <div>Memory</div>
        </div>
      
      
        <div class="license-meta-item license-meta-date">
          <div>发布于</div>
          <div>2023年9月19日</div>
        </div>
      
      
        <div class="license-meta-item license-meta-date">
          <div>更新于</div>
          <div>2023年11月18日</div>
        </div>
      
      
        <div class="license-meta-item">
          <div>许可协议</div>
          <div>
            
              
              
                <a target="_blank" href="https://creativecommons.org/licenses/by/4.0/">
                  <span class="hint--top hint--rounded" aria-label="BY - 署名">
                    <i class="iconfont icon-by"></i>
                  </span>
                </a>
              
            
          </div>
        </div>
      
    </div>
    <div class="license-icon iconfont"></div>
  </div>



              
                <div class="post-prevnext my-3">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/deng-2022/blog_2/2023/09/22/%E6%8E%A2%E7%B4%A2%20GitHub%EF%BC%9A%E5%8F%82%E4%B8%8E%E5%BC%80%E6%BA%90%E9%A1%B9%E7%9B%AE%E7%9A%84%E6%AD%A5%E9%AA%A4%E4%B8%8E%E6%8A%80%E5%B7%A7/" title="探索GitHub：参与开源项目的步骤与技巧">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">探索GitHub：参与开源项目的步骤与技巧</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/deng-2022/blog_2/2023/09/17/%E6%94%B9%E5%8F%98%E7%BC%96%E7%A0%81%E6%B8%B8%E6%88%8F%E8%A7%84%E5%88%99%EF%BC%9A%E6%8F%AD%E7%A7%9823%E7%A7%8D%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%9A%84%E9%AD%85%E5%8A%9B%E5%92%8C%E5%AE%9E%E7%94%A8%E6%80%A7/" title="改变编码游戏规则：揭秘23种设计模式的魅力和实用性">
                        <span class="hidden-mobile">改变编码游戏规则：揭秘23种设计模式的魅力和实用性</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
  
  
    <article id="comments">
      

    </article>
  


          </article>
        </div>
      </div>
    </div>

    <div class="side-col d-none d-lg-block col-lg-2">
      
  <aside class="sidebar" style="margin-left: -1rem">
    <div id="toc">
  <p class="toc-header">
    <i class="iconfont icon-list"></i>
    <span>目录</span>
  </p>
  <div class="toc-body" id="toc-body"></div>
</div>



  </aside>


    </div>
  </div>
</div>





  



  



  



  



  







    

    
      <a id="scroll-top-button" aria-label="TOP" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v" for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>

    

    
  </main>

  <footer>
    <div class="footer-inner">
  
    <div class="footer-content">
       <a href="https://hexo.fluid-dev.com/docs/guide/" target="_blank" rel="nofollow noopener"> <span>Memory | 个人文档站点</span> </a>
<i class="iconfont icon-love"></i> <a href="https://hexo.fluid-dev.com/docs/guide/" target="_blank" rel="nofollow noopener"> <span>配置指南 | Hexo Fluid 用户手册</span> </a>   
    </div>
  
  
    <div class="statistics">
  
  

  
    
      <span id="leancloud-site-pv-container" style="display: none">
        总访问量 
        <span id="leancloud-site-pv"></span>
         次
      </span>
    
    
      <span id="leancloud-site-uv-container" style="display: none">
        总访客数 
        <span id="leancloud-site-uv"></span>
         人
      </span>
    
    

  
</div>

  
  
    <!-- 备案信息 ICP for China -->
    <div class="beian">
  <span>
    <a href="http://beian.miit.gov.cn/" target="_blank" rel="nofollow noopener">
      京ICP证123456号
    </a>
  </span>
  
    
      <span>
        <a
          href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=12345678"
          rel="nofollow noopener"
          class="beian-police"
          target="_blank"
        >
          
            <span style="visibility: hidden; width: 0">|</span>
            <img src="/deng-2022/blog_2/img/police_beian.png" alt="police-icon"/>
          
          <span>京公网安备12345678号</span>
        </a>
      </span>
    
  
</div>

  
  
</div>

  </footer>

  <!-- Scripts -->
  
  <script  src="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://lib.baomitu.com/jquery/3.6.0/jquery.min.js" ></script>
<script  src="https://lib.baomitu.com/twitter-bootstrap/4.6.1/js/bootstrap.min.js" ></script>
<script  src="/deng-2022/blog_2/js/events.js" ></script>
<script  src="/deng-2022/blog_2/js/plugins.js" ></script>


  <script  src="https://lib.baomitu.com/typed.js/2.0.12/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var subtitle = document.getElementById('subtitle');
      if (!subtitle || !typing) {
        return;
      }
      var text = subtitle.getAttribute('data-typed-text');
      
        typing(text);
      
    })(window, document);
  </script>







  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/tocbot/4.18.2/tocbot.min.js', function() {
    var toc = jQuery('#toc');
    if (toc.length === 0 || !window.tocbot) { return; }
    var boardCtn = jQuery('#board-ctn');
    var boardTop = boardCtn.offset().top;

    window.tocbot.init(Object.assign({
      tocSelector     : '#toc-body',
      contentSelector : '.markdown-body',
      linkClass       : 'tocbot-link',
      activeLinkClass : 'tocbot-active-link',
      listClass       : 'tocbot-list',
      isCollapsedClass: 'tocbot-is-collapsed',
      collapsibleClass: 'tocbot-is-collapsible',
      scrollSmooth    : true,
      includeTitleTags: true,
      headingsOffset  : -boardTop,
    }, CONFIG.toc));
    if (toc.find('.toc-list-item').length > 0) {
      toc.css('visibility', 'visible');
    }

    Fluid.events.registerRefreshCallback(function() {
      if ('tocbot' in window) {
        tocbot.refresh();
        var toc = jQuery('#toc');
        if (toc.length === 0 || !tocbot) {
          return;
        }
        if (toc.find('.toc-list-item').length > 0) {
          toc.css('visibility', 'visible');
        }
      }
    });
  });
</script>


  <script src=https://lib.baomitu.com/clipboard.js/2.0.11/clipboard.min.js></script>

  <script>Fluid.plugins.codeWidget();</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/anchor-js/4.3.1/anchor.min.js', function() {
    window.anchors.options = {
      placement: CONFIG.anchorjs.placement,
      visible  : CONFIG.anchorjs.visible
    };
    if (CONFIG.anchorjs.icon) {
      window.anchors.options.icon = CONFIG.anchorjs.icon;
    }
    var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
    var res = [];
    for (var item of el) {
      res.push('.markdown-body > ' + item.trim());
    }
    if (CONFIG.anchorjs.placement === 'left') {
      window.anchors.options.class = 'anchorjs-link-left';
    }
    window.anchors.add(res.join(', '));

    Fluid.events.registerRefreshCallback(function() {
      if ('anchors' in window) {
        anchors.removeAll();
        var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
        var res = [];
        for (var item of el) {
          res.push('.markdown-body > ' + item.trim());
        }
        if (CONFIG.anchorjs.placement === 'left') {
          anchors.options.class = 'anchorjs-link-left';
        }
        anchors.add(res.join(', '));
      }
    });
  });
</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.js', function() {
    Fluid.plugins.fancyBox();
  });
</script>


  <script>Fluid.plugins.imageCaption();</script>

  <script  src="/deng-2022/blog_2/js/local-search.js" ></script>

  <script defer src="/deng-2022/blog_2/js/leancloud.js" ></script>





<!-- 主题的启动项，将它保持在最底部 -->
<!-- the boot of the theme, keep it at the bottom -->
<script  src="/deng-2022/blog_2/js/boot.js" ></script>


  

  <noscript>
    <div class="noscript-warning">博客在允许 JavaScript 运行的环境下浏览效果更佳</div>
  </noscript>
</body>
</html>
